Coding the JavaFX TableView
At first glance, using the JavaFX 2 TableView control may seem confusing. But after you have the first "Aha!" moment with it, you'll see just how easy it is to use. Thanks to JavaFX binding and the new JavaFX Scene Builder, it's all cake. Here's a sample test app, with step-by-step explanations, that serve as a roadmap to building your own table-based JavaFX applications.
Step 1: Create the Project
If you have the latest Java SE 1.7 installed (Update 4), then you have JavaFX by default — it's bundled with it. Otherwise, you can download and install it separately here. Remember, you can develop JavaFX 2.0 applications with either Java SE 1.6 or 1.7.
After JavaFX is installed, create a new JavaFX project. This is very easy with the latest NetBeans, but you can use any IDE you'd like. For now, I'll assume you're using NetBeans.
Next, give the project a name, and NetBeans generates everything you need to begin. As a result, you'll get a small application with a main class that looks like this:
public class TestJavaFX extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Hello World!"); Button btn = new Button(); btn.setText("Say 'Hello World'"); btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Hello World!"); } }); StackPane root = new StackPane(); root.getChildren().add(btn); primaryStage.setScene(new Scene(root, 300, 250)); primaryStage.show(); } }
Step 2: Define the UI Layout
Before we modify any code, however, we'll need to define the UI layout. It's easiest to do this with the JavaFX Scene Builder, which I've written about in a previous Dr. Dobb's blog. Open Scene Builder and add a TableView control to the canvas. Drag four TableColumn controls onto the table, and assign them the text names: "ID", "Item Name", "Qty", and "Price", respectively. Finally, add a button control below the table, and name it "Add Item". We'll use this button to add items to the table for illustration. It should look like this:
Save your Scene Builder work, saving the resulting FXML file in the same directory as your application's source code. Next, in the Document section on the right side of the Scene Builder window, make sure you choose your project's main class as the controller. It's important that these steps be performed in that order.
Step 3: Add the Controls to the Code
Go back to NetBeans, and prepare to make some simple modifications to the code. First, add the following FXML control declarations to the main class:
@FXML TableView<InvoiceEntry> invoiceTbl; @FXML TableColumn itemIdCol; @FXML TableColumn itemNameCol; @FXML TableColumn itemQtyCol; @FXML TableColumn itemPriceCol; @FXML Button addItemBtn;
Since InvoiceEntry
isn't defined yet, this code won't compile. Create this class now as defined below, and then fix the imports so the code will compile (in NetBeans, right-click on the code and choose "Fix Imports" from the menu).
import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleStringProperty; public class InvoiceEntry { public SimpleIntegerProperty itemId = new SimpleIntegerProperty(); public SimpleStringProperty itemName = new SimpleStringProperty("<Name>"); public SimpleStringProperty price = new SimpleStringProperty(); public SimpleIntegerProperty qty = new SimpleIntegerProperty(); public int invoiceId; public Integer getItemId() { return itemId.get(); } public String getItemName() { return itemName.get(); } public String getPrice() { return price.get(); } public Integer getQty() { return qty.get(); } }
Note: It's very important that this class contains getter methods for the data items that map to columns in the table. This is how JavaFX performs its magic and reduces the code you need to write. It calls the getters automatically, as long as they conform to the normal JavaBeans naming patterns for class data.
Finally, add an empty onAddItem()
method to map to the button, as shown here:
public void onAddItem(ActionEvent event) { }