I am trying to set up a netbeans/javafx program that displays a list of Pet objects, and gives every row an onclick listener.
I have the following in fxml:
MyTables.fxml
<VBox alignment="CENTER" layoutX="11.0" layoutY="12.0" prefWidth="345.0">
<children>
<TableView id="Table1" fx:id="Table1" styleClass="mytable"/>
<TableView id="Table2" fx:id="Table2" styleClass="mytable"/>
<TableView id="Table3" fx:id="Table3" styleClass="mytable"/>
<TableView id="Table4" fx:id="Table4" styleClass="mytable"/>
</children>
</VBox>
I'm using netbeans, so I set up a topComponent for the view which loads the FXML, which in turn loads a controller class.
In my controller class I have the following code to add content to the table. The intention is for each table to have 3 rows that correspond to the ID, Name, and Owner of the contained Pet object.
MyTablesController.java
public class MyTablesController implements Initializable {
@FXML
private TableView<Pet> Table1;
@FXML
private TableView<Pet> Table2;
@FXML
private TableView<Pet> Table3;
@FXML
private TableView<Pet> Table4;
private TableView<Pet>[] allTables;
public MyTablesController() {
allTables = new TableView[4];
allTables[0] = Table1;
allTables[1] = Table2;
allTables[2] = Table3;
allTables[3] = Table4;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
for(TableView<Pet> table : allTables) {
table.getColumns().add(createCol("ID", Pet::idProperty, 100));
table.getColumns().add(createCol("Name", Pet::nameProperty, 140));
table.getColumns().add(createCol("Owner", Pet::ownerProperty, 100));
table.getItems().addAll(
new Pet("1234", "spot", "joe"),
new Pet("5432", "snowball", "bill"),
new Pet("7612", "snoopy", "frank")
);
}
setupTableRowDragEvents();
}
private TableColumn<Pet, String> createCol(String title,
Function<Pet, ObservableValue<String>> mapper, double size) {
TableColumn<Pet, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> mapper.apply(cellData.getValue()));
col.setPrefWidth(size);
return col ;
}
private void setupTableRowDragEvents() {
for (TableView<Pet> table : allTables) {
table.setRowFactory(tv -> {
TableRow<Pet> row = new TableRow<>();
row.setOnMouseClicked(event -> {
System.out.println("I CLICKED ON " + row.getItem().getName()");
});
return row;
});
}
}
}
Finally, here is the Pet object:
Pet.java
public final class Pet {
public final StringProperty id = new SimpleStringProperty(this, "id");
public final StringProperty name = new SimpleStringProperty(this, "name");
public final StringProperty owner = new SimpleStringProperty(this, "owner");
public Pet() {}
public Pet(String id, String name, String owner) {
this.id.set(id);
this.name.set(name);
this.owner.set(owner);
}
public String getId() {
return id.get();
}
public void setId(String id) {
this.id.set(id);
}
public StringProperty idProperty() {
return id;
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
public String getOwner() {
return owner.get();
}
public void setOwner(String owner) {
this.owner.set(owner);
}
public StringProperty ownerProperty() {
return owner;
}
}
Here's my problem.
If I leave MyTablesController.initialize empty, the 4 graphs display just fine. It's only when I add the rest of the code (the setCols calls and the setupTableRowDragEvents() call)...
The graphs don't display if either or both of the those things in initialize() exist. I get no error message or strange behavior other than the window being totally empty and the graphs not showing up.
I'm basing my code off of sort tableview with drag and drop (rows) . I can't figure out where I'm screwing up when compared to this. Is that answer just wrong and nobody bothered to check it?
What am I doing wrong here?
At the time you populate the array, the table view references are all null
, so you fill your array with null references. Then when you iterate through the array, you will get a null pointer exception the first time you call table.getColumns()
. Move the code from the controller constructor to the beginning of initialize()
:
public class MyTablesController implements Initializable {
@FXML
private TableView<Pet> Table1;
@FXML
private TableView<Pet> Table2;
@FXML
private TableView<Pet> Table3;
@FXML
private TableView<Pet> Table4;
private TableView<Pet>[] allTables;
@Override
public void initialize(URL location, ResourceBundle resources) {
allTables = new TableView[4];
allTables[0] = Table1;
allTables[1] = Table2;
allTables[2] = Table3;
allTables[3] = Table4;
for(TableView<Pet> table : allTables) {
table.getColumns().add(createCol("ID", Pet::idProperty, 100));
table.getColumns().add(createCol("Name", Pet::nameProperty, 140));
table.getColumns().add(createCol("Owner", Pet::ownerProperty, 100));
table.getItems().addAll(
new Pet("1234", "spot", "joe"),
new Pet("5432", "snowball", "bill"),
new Pet("7612", "snoopy", "frank")
);
}
setupTableRowDragEvents();
}
// ...
}