How to "Pretty Up" Your JavaFX TableViews
By MkHeck on Feb 26, 2013
I'd always intended to create some small-but-useful Twitter utilities and hadn't really had the opportunity, but a simple Twitter client provides a perfect demonstration of this capability. Here is an example of what a "feed" interface might look like:
For this TableView example, there are only two columns:
- one for the user, showing the user's picture, name, and screen name
- one for the tweet
The tweet's text is simply a string property of each MTweet object, but the user information comes from several properties of the MTweet object's associated MUser object. The MTweet's text is properly assigned to the cell's text property per the discussion above, but what about the user information? Per the JavaFX 2.2 docs,
Labeled. This means that subclasses of Cell need only set the
textproperty, rather than create a separate
Labeland set that within the Cell. However, for situations where something more than just plain text is called for, it is possible to place any
Nodein the Cell
graphicproperty. Despite the term, a graphic can be any Node, and will be fully interactive. For example, a ListCell might be configured with a
Buttonas its graphic. The Button text could then be bound to the cells
itemproperty. In this way, whenever the item in the Cell changes, the Button text is automatically updated.
To display the tweet's text in the "Text" column of our table, a couple lines of code does all that is necessary:
In order to bundle the user information and place it within a single cell, we set the "User Info" column's CellValueFactory in similar fashion to our text column above:
And then we set that column's CellFactory to something along the order of this:
For each cell in that TableColumn, updateItem is called with that cell's contents as the "item", the first parameter. Within our example above, we create a VBox, populate it with the user's photo (Image, via ImageView), name (String) and screen name (String), do a bit of formatting, and assign the VBox to the cell's graphic property. And with that, we're off and running. :-)
There is much more you can do, and this should get the ideas flowing. Here's to prettier apps (better optics?) and happier users!
<<< UPDATE 1 >>>
Jonathan Giles, JavaFX team UI Controls tech lead, made a few suggestions for improving the efficiency of the code used above. The points he made were excellent, and I wanted to provide an update that shows revised code that incorporates them. I did leave the original code above, as I'm hoping it helps make a clearer path for those implementing similar code for the first time.
In order to override the TableCell constructor, we'll extend the particular TableCell<MTweet, MUser> class. Doing so allows us to create the VBox, Labels, and ImageView used in our composite user cell once per cell, rather than each time updateItem() is called. While we're at it, we'll also perform formatting/assignment duties in the constructor and avoid repeating those calls. Here is the new derivative class:
Creating the new UserTableCell class means we can update our setCellFactory() method call for our user info column like so:
Thanks to Jonathan Giles (@JonathanGiles) for the suggestions!
All the best,
<<< UPDATE 2 >>>
One more update! This time using an anonymous inner class for the column's cell factory. Same basic functionality, but this is perhaps the tidiest option.
Options are good, as they say... :-)
All the best,