I'm trying to create a very simple custom ListCell
for a JavaFX Listview
. When running the Application there are Items in the ListView
without any content. They're clickable but empty. Like following image shows:
I'm using JDK 12 and a Maven JFX Archetype(archetype-artifactid:javafx-archetype-fxml, groupid:org.openjfx) based setup. I followed a guide called "Turais Custom ListCell".
App.java
public class App extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
scene = new Scene(loadFXML("primary"));
stage.setScene(scene);
stage.show();
}
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
private static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
return fxmlLoader.load();
}
public static void main(String[] args) {
launch();
}
}
PrimaryController.java
public class PrimaryController implements Initializable {
ObservableList<Student> students;
@FXML
private ListView<Student> listView1;
@FXML
private void switchToSecondary() throws IOException {
App.setRoot("secondary");
}
public PrimaryController(){
super();
students = FXCollections.observableArrayList();
students.add(new Student());
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
listView1.setItems(students);
listView1.setCellFactory(new Callback<ListView<Student>, ListCell<Student>>() {
@Override
public ListCell<Student> call(ListView<Student> listView) {
return new StudentListViewCell();
}
});
}
}
Primary.fxml
<VBox alignment="CENTER" prefHeight="257.0" prefWidth="230.0" spacing="20.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.test.PrimaryController">
<children>
<Label text="Primary View" />
<Button fx:id="primaryButton" onAction="#switchToSecondary" text="Switch to Secondary View" />
<ListView fx:id="listView1" prefHeight="200.0" prefWidth="200.0" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
ListCell.fxml
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label fx:id="label1" layoutX="293.0" layoutY="190.0" text="Label" />
</children>
</AnchorPane>
StudentListViewCell.java
public class StudentListViewCell extends ListCell<Student> {
@FXML
private Label label1;
@FXML
private AnchorPane anchorPane;
private FXMLLoader mLLoader;
@Override
protected void updateItem(Student student, boolean empty) {
super.updateItem(student, empty);
if(empty || student == null) {
setText(null);
setGraphic(null);
} else {
if (mLLoader == null) {
mLLoader = new FXMLLoader(getClass().getResource("ListCell.fxml"));
mLLoader.setController(this);
try {
mLLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
label1.setText("rightText");
setText(null);
setGraphic(anchorPane);
}
}
}
Student.java
public class Student {
private String name;
public Student(String name){
this.name = name;
}
}
I'd expect a single ListCell
which has a label in the middle with "rightText" written in it. But it seems like my custom listcell is not even rendered. Any suggestions?
Aside from your implementation appearing to be much more complex than it needs to be, your actual issue is a very simple one.
Your ListCell.fxml
file does not assign an fx:id
to your AnchorPane
. Therefore, when you define it in your StudentListViewCell.java
class, you're essentially creating a new AnchorPane
, and one that does not contain your Label
.
Simply changing your ListCell.fxml
file and assigning the id will fix that issue:
<AnchorPane fx:id="anchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label fx:id="label1" layoutX="293.0" layoutY="190.0" text="Label"/>
</children>
</AnchorPane>