JavaFX TableView Sample Project
In June, I wrote a quick piece on how to use the JavaFX 2 TableView control with SceneBuilder and FXML. This has proven to be one of my most popular blogs recently, but I've received feedback that some readers are still having difficulty getting their own TableView code to work as expected. Although I included code snippets throughout my blog, it would have helped if I had included a single, standalone TableView project for readers to build and work with on their own. The code I did include at the time was part of a larger project, which I'm not at liberty to distribute.
However, I've created a standalone TableView example project, complete with NetBeans project files, which you can download. Here's a quick summary of the approach.
The first step, as outlined in my previous blog, is to create the project. Java SE 1.7 and the latest NetBeans (v 7.2) have built-in support for JavaFX. You should also download and install the JavaFX SceneBuilder, which makes it much easier to lay out your JavaFX visual components. It integrates with the FXML and Java class files generated as part of your NetBeans projects, and saves a lot of time and effort.
The next step is to lay out the components of your application on the canvas that the JavaFX SceneBuilder provides, as well as to define the controls in your code to hook up to. This was all outlined in my previous blog so feel free to peruse that for a quick reminder.
Finally, you need to create a class that represents the data that gets added to the TableView. This is the tricky part: The variables that represent the column data need to be JavaFX properties (i.e SimpleStringProperty) and have getter methods with the proper names defined. Also, the TableView entry needs to be placed in an ObservableList, and set as the table's data property. All of this can be seen in the code below. Now, by simply created a new object of your entry class, and then adding it to the TableView's "items" property, new entries will simply appear in the table (thanks to binding). Additionally, changes to any of the properties of an existing table entry will also appear in the table (again thanks to binding).
Use this code as a starting point for your own projects. Carefully modify the table's column definition, along with the class that represents each entry in the table, to customize it for your own application. Please feel free to contact me or leave a comment if you need help of clarification.
Happy coding!
-EJB
public class SampleController implements Initializable {
public class Item {
public SimpleLongProperty id = new SimpleLongProperty();
public SimpleStringProperty name = new SimpleStringProperty();
public SimpleIntegerProperty qty = new SimpleIntegerProperty();
public SimpleStringProperty price = new SimpleStringProperty();
public Long getId() {
return id.get();
}
public String getName() {
return name.get();
}
public String getPrice() {
return price.get();
}
public Integer getQty() {
return qty.get();
}
}
// The table and columns
@FXML
TableView<Item> itemTbl;
@FXML
TableColumn itemIdCol;
@FXML
TableColumn itemNameCol;
@FXML
TableColumn itemQtyCol;
@FXML
TableColumn itemPriceCol;
// The table's data
ObservableList<Item> data;
@Override
public void initialize(URL url, ResourceBundle rb) {
// Set up the table data
itemIdCol.setCellValueFactory(
new PropertyValueFactory<Item,Long>("id")
);
itemNameCol.setCellValueFactory(
new PropertyValueFactory<Item,String>("name")
);
itemQtyCol.setCellValueFactory(
new PropertyValueFactory<Item,Integer>("qty")
);
itemPriceCol.setCellValueFactory(
new PropertyValueFactory<Item,String>("price")
);
data = FXCollections.observableArrayList();
itemTbl.setItems(data);
}
static long nextId = 1;
@FXML
private void handleButtonAction(ActionEvent event) {
Item item = new Item();
item.id.setValue(nextId++);
item.name.setValue("Item Number " + item.id.getValue());
item.qty.setValue(10);
Float price = new Float(5.00 + (float)item.id.getValue());
item.price.setValue( price.toString() );
data.add(item);
}
}
Below is the FXML for the scene layout:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="500.0" xmlns:fx="http://javafx.com/fxml" fx:controller="tableviewfxmlsample1.SampleController">
<children>
<Button fx:id="button" layoutX="406.0" layoutY="365.0" onAction="#handleButtonAction" text="Add Row" />
<Label fx:id="label" layoutX="126.0" layoutY="120.0" minHeight="16.0" minWidth="69.0" />
<TableView fx:id="itemTbl" layoutX="14.0" layoutY="14.0" prefHeight="334.0" prefWidth="470.0">
<columns>
<TableColumn prefWidth="75.0" text="Item ID" fx:id="itemIdCol" />
<TableColumn prefWidth="243.0" text="Item Name" fx:id="itemNameCol" />
<TableColumn prefWidth="75.0" text="Qty" fx:id="itemQtyCol" />
<TableColumn prefWidth="75.0" text="Price" fx:id="itemPriceCol" />
</columns>
</TableView>
</children>
</AnchorPane>

