Reputation: 41
I am using the JavaFX ListView component and want to use a custom cell factory. When the dialog containing the list view is opened the items are rendered correctly. However, if I try to add or delete an item from the underlying observable list, the items in the list view are not rendered correctly. I will have cells duplicated or missing altogether. Here is the FXML for my custom cell:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import org.controlsfx.glyphfont.Glyph?>
<VBox fx:id="vbox" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="150.0" prefWidth="300.0" spacing="5.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Label fx:id="nameLabel" style="-fx-font-weight: bold; -fx-font-size: 14;" text="Mr Stephen Lowe" />
<Label fx:id="mobileLabel" text="07798933862">
<graphic>
<Glyph fontFamily="FontAwesome" icon="PHONE" />
</graphic>
<font>
<Font size="12.0" />
</font>
</Label>
<Label fx:id="emailLabel" text="[email protected]">
<graphic>
<Glyph fontFamily="FontAwesome" icon="ENVELOPE" />
</graphic>
<font>
<Font size="12.0" />
</font>
</Label>
<Label fx:id="churchMemberLabel" text="Church Member" textFill="#388e3c">
<font>
<Font size="12.0" />
</font></Label>
</children>
</VBox>
and here is my custom ListCell subclass:
/**
*
* @author Stephen
*/
public class MemberListViewCell extends ListCell<MemberEntity> {
@FXML
private Label nameLabel;
@FXML
private Label mobileLabel;
@FXML
private Label emailLabel;
@FXML
private Label churchMemberLabel;
@FXML
private VBox vbox;
private FXMLLoader loader;
public MemberListViewCell() {
}
@Override
protected void updateItem(MemberEntity item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
if (loader == null) {
loader = new FXMLLoader(getClass().getResource("/fxml/listcell.fxml"));
loader.setController(this);
try {
loader.load();
} catch (IOException ex) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Open FXML");
alert.setHeaderText("FXML Error");
String msg = "Could not load FXML for list cell factory. Inform software engineer. Terminating program.";
msg += ex.toString();
alert.setContentText(msg);
alert.showAndWait();
System.exit(1);
}
}
nameLabel.setText(item.getName().getFormattedName(Name.NameFormat.FORENAME_SURNAME));
mobileLabel.setText(item.getMobileTelephone());
emailLabel.setText(item.getEmailAddress());
if (item.isChurchMember()) {
churchMemberLabel.setText("Church Member");
churchMemberLabel.setTextFill(Paint.valueOf("#388e3c"));
} else {
churchMemberLabel.setText("Not Church Member");
churchMemberLabel.setTextFill(Paint.valueOf("#d32f2f"));
}
setText(null);
setGraphic(vbox);
}
}
}
Upvotes: 0
Views: 292
Reputation: 209340
Since you set the graphic for non-empty cells, you need to set it back to null if the cell becomes empty:
@Override
protected void updateItem(MemberEntity item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
// existing code ...
}
}
Upvotes: 2