TableView: display tables in JavaFX

If you were used to use JTable in Swing in order to display tables in your UI, you probably know that was kind of difficult to use and customise. In JavaFX you have what is called a TableView which is complex component allowing you to do a lot of stuff. In this post we will try to cover some basics about the TableView.

Main classes

In order to display tables in JavaFX you will use a TableView. The TableView will host TableColumns. That are the two main classes you will use in order to create a table. The TableRow class also exists but you won’t use it much, except if you want to create your own rowFactory. But that is a bit out of the scope of this post.

Bring up some Generics

A table is a container that will host some kind of data: a product, an account, an item, etc. So your TableView will host some kind of data. So the following declaration makes sense:

TableView<Property> propertiesTable = new ...

Columns will host a specific value of an item in the table, like the name of the product for example. And the name is a string. So declaring columns will be like this:

TableColumn<Property, String> nameColumn;
TableColumn<Property, String> valueColumn;

The power of properties

One of the great concept of JavaFX 2 is the properties and binding (read about here). And it is very useful in our case. Indeed we know what to display in our table, we have the data but I don’t want to say each time I need a new entry in my table that the name is in the first column, the value in the second, and so on. So let’s have a look. First of all I’m going to create a JavaBean with properties:

public class Property implements Serializable {
  public enum Type {
    SYSTEM, ENVIRONMENT
  }

  private final StringProperty name = new SimpleStringProperty();
  private final StringProperty value = new SimpleStringProperty();
  private final ObjectProperty<Type> type = new SimpleObjectProperty<>();
    
  public Property() {
  }
    
  public Property(String name, String value, Type type) {
    this.name.set(name);
    this.value.set(value);
    this.type.set(type);
  }
    
  public final StringProperty nameProperty() {
    return this.name;
  }
    
  public final String getName() {
    return this.nameProperty().get();
  }
    
  public final void setName(String name) {
    this.nameProperty().set(name);
  }
    
  public final StringProperty valueProperty() {
    return this.value;
  }
    
  public final String getValue() {
    return this.valueProperty().get();
  }
    
  public final void setValue(String value) {
    this.valueProperty().set(value);
  }
    
  public final ObjectProperty<Type> typeProperty() {
    return this.type;
  }
    
  public final Type getType() {
    return this.typeProperty().get();
  }

  public final void setType(Type type) {
    this.typeProperty().set(type);
  }
}

This quite simple. But now the real power will be revealed. We will create our table completely in FXML, without anything else. But you can of course create your table completely using pure Java code (just have a look on the Oracle website).

<BorderPane prefHeight="800" prefWidth="1000" fx:id="rootPane"
    xmlns:fx="http://javafx.com/fxml"
    fx:controller="com.twasyl.envviewer.controllers.EnvViewerController">
  <center>
    <TableView fx:id="propertiesTable">
      <columns>
        <TableColumn text="Type" fx:id="typeColumn">
          <cellValueFactory>
            <PropertyValueFactory property="type" />
          </cellValueFactory>
        </TableColumn>
        <TableColumn text="Name" fx:id="nameColumn">
          <cellValueFactory>
            <PropertyValueFactory property="name" />
          </cellValueFactory>
        </TableColumn>
        <TableColumn text="Value" fx:id="valueColumn">
          <cellValueFactory>
            <PropertyValueFactory property="value" />
          </cellValueFactory>
        </TableColumn>
      </columns>
    </TableView>
  </center>
</BorderPane>

And now take a look at the controller:

public class EnvViewerController implements Initializable {
    
  @FXML
  private Pane rootPane;
  @FXML
  private TableView<Property> propertiesTable;
  @FXML
  private TableColumn<Property, String> nameColumn;
  @FXML
  private TableColumn<Property, String> valueColumn;
  @FXML
  private TableColumn<Property, Type> typeColumn;
    
  @Override
  public void initialize(URL url, ResourceBundle rb) {
  }
}

As you can read, each TableColumn tag has a cellValueFactory one, which have a PropertyValueFactory. And this last one has an attribute named property. So what about everything? That simply means the column is bound to a property of the main content of the table. In other words, our table contains some Property objects (our JavaBean class) and the first column is bound to the type property, the second to the name one and the third to the value. Easy right? Here is a little screenshot:
Empty EnvViewer
Now we will modify our controller class in order to add some items to our table:

@Override
public void initialize(URL url, ResourceBundle rb) {
        
  for(Map.Entry entry : System.getProperties().entrySet()) {
    propertiesTable.getItems().add(new Property(entry.getKey().toString(), entry.getValue().toString(), Type.SYSTEM));
  }
        
  for(Map.Entry entry : System.getenv().entrySet()) {
    propertiesTable.getItems().add(new Property(entry.getKey().toString(), entry.getValue().toString(), Type.ENVIRONMENT));
  }
}

And this is what you get:
EnvViewer filled
And the TableView comes with nice features like having sortable columns by default, you can move columns, and so on. These features were long to develop in Swing so JavaFX brings some really nice feature natively.

Of course you can do a lot more with TableViews, like editing the data, respond to user’s clicks, dynamically add data, customise the look & feel and so on. Maybe I’ll blog about some other features.

The code is from a little app I’ve done and that I’ll update to provide new features. You can find it here.

PS: this blog post took me much more time to write than coding the app, just saying!

About these ads

2 Responses to TableView: display tables in JavaFX

  1. Pingback: TableView: column’s width using percentage in JavaFX « System.out.println("Thierry WASYL : Java blog")

  2. Pingback: Java desktop links of the week, December 3 | Jonathan Giles

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: