Can There Be Too Much of a Good Thing?

I recently worked on JavaFX UI code that was new to me. In order to extend the existing UI by a simple label, I needed access to a bean of the underlying data model. Much to my surprise, I had to dig deep to find it hidden under multiple layers of wrappers. This was the data structure:

A bean wrapped in a BeanWrapper wrapped in an ObjectProperty wrapped in a WrapperPropertyProxy. Quite impressive.

Wow. Clearly, someone tried to satisfy their fetish for wrappers and indirection. I’m going show this image to the next computer science student I come across and ask them how many design (anti-)patterns they can see.

Headless UI Testing with TestFX and JavaFX 8

JavaFX is a great UI toolkit. TestFX is a great library for testing the user interfaces written in JavaFX. Writing graphical tests with TestFX is simple and fast, but one challenge remains when you build your software using a headless build machine: how can you perform your UI tests in headless mode during your build?

Luckily, JavaFX 8 Update 20 will contain Monocle, which should allow us to run these headless tests.

First analysis using the latest beta of JDK 8u20 indicates that these tests are feasible, but require some changes in the TestFX library. We used a simple standalone JavaFX application for which we wrote a basic TestFX test class. We ran this test using the following command line options:

Unfortunately, this was not enough to make the test work. So we took a deeper look at the inner workings of TestFX and found that a working solution required the following changes:

  1. refactor a part of the TestFX code such that different implementations of the org.loadui.testfx.framework.robot.ScreenRobot interface can be used. This allowed us to make test use an other robot implementation, in this case an adapter for MonocleRobot. The current TestFX implementation relies on java.awt.Robot, which uses the system event queue to move the system cursor. This, of course, does not integrate with Monocle in headless mode.
  2. implement a ScreenRobot adapter for MonocleRobot. MonocleRobot is in internal package and thus not available via public API. In order to obtain an instance of this class, we had to call:

This setup gave us a green test eventually. đŸ™‚

A Combined LineChart and TableView Widget in JavaFX
(enlarge to see more details)

This video shows a widget for displaying three characteristics (velocity vs. distance) in a LineChart node and a tabbed TableView node. The two nodes provide different views on the same data.

The widget comes with the following features:

  • hovering over a data point in the chart will show a popup with the x and y values.
  • selecting a data point in the chart will select the corresponding data item in the table view and vice versa.
  • when a data item was edited in the table view, the chart will update immediately.
  • three colour pickers allow for changing the line colours in the chart.
  • import and export data from sources like CSV, Excel, HDF5 (to be done).

These features were implemented using JavaFX bindings, events, animations, and CSS styling.

A Widget Picker Control in JavaFX

The following video shows a custom control in JavaFX that lets you select items from a list and position them in a grid. The items represent UI widgets, that is, JavaFX controls, with a defined size on the grid. The grid represents a page on which these widgets will be shown.

A Graph Editor in JavaFX

Another thing we’ve been working on is going to see the light of day soon: a graph editor for JavaFX. The current beta version provides the following main features:

  • create draggable, resizable nodes and connections between them
  • add multiple input or output connectors to a node
  • create joints inside a connection
  • add custom skins for nodes, connections, connectors, and joints
  • enhanced user experience through comprehensive styling during drag-and-drop actions

Internally, we use an EMF model to represent the UI objects and their state. The model is in sync with the UI at all times.

Here’s a short video of our current development version: