Using ICEpdf with JavaFX

Any developer in the Swing/AWT space has surely taken notice of JavaFX at some point over the last nine years. I was lucky enough to be at JavaOne in May of 2007 and saw the keynote where JavaFX was first announced. The presenter was dragging applications out the browser onto the desktop. The audience was shown all these little CSS file snippets and introduced to a newfangled scripting language. It all looked pretty cool, but as it turned out it was far from ready and it would be another year and half before the first official release. Personally, I kind forgot about JavaFX, I knew it was out there but was anyone using it?

In the last year interest in a JavaFX has increased significantly via our support channels which is generally a good barometer of technology change. As part of our support obligations we have spent quite a bit of time testing and integrating the ICEpdf Swing RI inside a JavaFX application. During this integration, we discovered a few notable things that other Swing/JavaFX developers might find helpful.

Component Size

A Swing component’s size is generally defined by a parent container which at the top level is usually a JFrame. Resizing of components in this hierarchy is very well defined, generally child elements are resized and fit into the given parent. When a JPanel is added to a SwingNode the layout doesn’t seem to be as predictable especially for a complex component. The general behavior we observed was that if a SwingNode’s children had a larger preferred size than the SwingNode’s initial size the Swing components would likely be clipped or not painted at all. In our default viewer component the JToolbar seemed to be the root of the problem as was our bottom toolbar which also has a custom layout manager. The solution for us was to break the RI’s main components into separate SwingNodes by leveraging the SwingBuilder class.

// add toolbar to the top.
FlowPane toolBarFlow = new FlowPane();
JToolBar mainToolbar = factory.buildCompleteToolBar(true);
buildJToolBar(toolBarFlow, mainToolbar);
borderPane.setTop(toolBarFlow);

// main utility pane and viewer
SwingNode swingNode = new SwingNode();
viewerPanel = factory.buildUtilityAndDocumentSplitPane(true);
swingNode.setContent(viewerPanel);
borderPane.setCenter(swingNode);

The SwingBuilder and SwingNode classes can also be used to build custom toolbars, or even just a single page view.

JPanel Resizing

The SwingNode when resized didn’t always seem to cause a repaint of a child JPanel. Our best guess here is that this related to how the JavaFX component scene event structure is so different than that of Swing/AWT. To get around the resizing issues we listened for the JavaFX resize event and propagated the event into the AWT event thread. Once again not a perfect solution but easy enough to implement.

private void createResizeListeners(Scene scene, JComponent viewerPanel) {
	scene.widthProperty().addListener((observable, oldValue, newValue) -> {
		SwingUtilities.invokeLater(() -> {
			viewerPanel.setSize(new Dimension(newValue.intValue(), (int) scene.getHeight()));
			viewerPanel.setPreferredSize(new Dimension(newValue.intValue(), (int) scene.getHeight()));
			viewerPanel.repaint();
		});
	});

	scene.heightProperty().addListener((observable, oldValue, newValue) -> {
		SwingUtilities.invokeLater(() -> {
			viewerPanel.setSize(new Dimension((int) scene.getWidth(), newValue.intValue()));
			viewerPanel.setPreferredSize(new Dimension((int) scene.getWidth(), newValue.intValue()));
			viewerPanel.repaint();
		});
	});
}

The Future

For Swing developers that haven’t experimented with JavaFX yet I highly recommend you give it a try. In a very short time you will be building user interfaces in a fraction of the time required when compared to Swing.  The API is elegant and very intuitive to work with, and it is easy to make the UI “pretty”. There is a lot of power to leverage here, including a very polished component suite. We would be very interested to hear back from our community and hear your thoughts about your migration plans for JDK 8 and if there are any plans to start using JavaFX for the next big project?

ICEpdf Development Team

Source Code

Full listing can be found here, http://www.icesoft.org/JForum/posts/list/23209.page

One thought on “Using ICEpdf with JavaFX

Leave a Reply

Your email address will not be published. Required fields are marked *

11 − seven =