Injecting the "extreme" into this year's GUI Makeover session at JavaOne, Jasper's finale of blowing up junk email with rocket explosions was really fun and of course completely absurd.
Looking beyond the antics, our message in the session was actually very practical:
You can blend the strengths of Swing and JavaFX to give your Java applications that visual edge that users are coming to expect from modern clients.
If you weren't able to attend the session you can download the GUI Makeover slides (I couldn't resisting drawing a mustache & beard on Chet's face in slide 6).
If you're a Swing developer who's both skeptical and curious about JavaFX, I've broken down the process into 10 steps for integrating your Swing components into a JavaFX application.
Note: We also recognize the need for the inverse (embedding a JavaFX scene into a Swing app), however that is not supported with 1.2 as it requires a more formal mechanism for manipulating JavaFX objects from Java code. The structure of these JavaFX objects is a moving target (for some very good reasons) and we're not ready to lock that down (yet). However,as with most software, this can be hacked (see Rich & Jasper's hack on Josh's blog) but know that you are laying compatibility down on the tracks if you go there.
Honestly, you can pull large portions of your Swing GUIs into JavaFX very easily...
0. Find Your Design Since every good list-of-10 should go to 11, I've inserted a Step 0 (really the most important step of all): use all means at your disposal to find a good design. If you arn't lucky enough to have that rare engineer who's good at both coding and visual design (e.g. a Jasper Potts or a Romain Guy) and you can't afford to hire a good designer, then study the interfaces you respect and "borrow" from them. The nicest interfaces use effects and animation in subtle ways to bring fluidity to the UI. Here are some random links on the subject (and I'd welcome suggested additions to this list):
1. Touch Base with the Language Turns out that most of the developers I encounter who have a negative impression of the JavaFX scripting language have actually never tried it. A little more than a year ago I was there too; it looked weird and I couldn't imagine why I'd ever want to use anything but Java to code my apps. But it turns out that using a language designed for interface construction is amazingly gratifying. I'll admit there was a little hump to get over in learning to think declaratively vs. procedurally, but once that clicked, I found I can't imagine living without the JavaFX script features of binding, function pointers, and sequences. So suspend your disbelief for just a moment and browse the tutorial: JavaFX Language Tutorial
Another critique I've heard is that the declarative, 'scripty' nature of JavaFX leads to unwieldy and hard-to-maintain code; to that I say that it is possible to write crappy code in any language and that JavaFX script does provide an object-oriented model well-suited to the discipline of nice class structure and well-factored code. Just keep using the skills that Java taught you.
2. Download the SDK Just do it. Go to javafx.com and click on the orange "Download Now" link. I recommend installing the NetBeans 6.5.1 bundle to get the JavaFX plugin automatically.
3. Create NetBeans Project You'll want to create a new JavaFX NetBeans project (File -> New Project...select "JavaFX" type). [Note: In the "Create Main File" checkbox, I usually change "Main" to a more descriptive classname for my app because I find it annoying to end up with a dozen "Main.fx" source tabs in NetBeans].
Once your project is there, you can just copy your existing Swing app source code into the "src" directory. For GUI Makeover, we placed the swing sources in their own subpackage for cleanliness. Another option would be to keep your Swing app source in its own Java project and create a jar file which your JavaFX project could use. In our case it was simpler to keep it all in a single project since we wanted to also make minor adjustments to the Swing code (tweaking colors, fonts, etc).
I'll take a moment to emphasize that the core of any serious application should remain in Java and I'm advocating that only the client veneer should be migrated to JavaFX (a good model for separation of concerns anyways). There are numerous reasons for this, but the glaring one is that JavaFX is single-threaded -- any code that needs to run off the main gui thread must execute in Java.
4. Create a Stage The root of all JavaFX interfaces is a Stage. When you created your JavaFX NetBeans project, it most likely generated a default Stage declaration in your main source file:
Customize that stage as desired. Stage has both a style and an opacity variable to make it really easy to create non-rectangular UIs. If you choose a StageStyle of TRANSPARENT or UNDECORATED you will have to provide your own input handling for managing the toplevel window in the user's environment (on desktop).
5. Define the Layout You'll need to replace the content of the stage's Scene with your own UI. In our case with GUI Makeover, our stage was composed of a mixture of FX-node-based panels and Swing components. Since our designer tool isn't yet shipping, you'll have to do this by hand and here's where I'll do a bit of hand-waving, as layout in any sophisticated graphical toolkit is impossible to cover in a paragraph or two. For an overview of JavaFX scene graph layout, you can check out the JavaOne UI Controls session slides where I presented layout in detail (starting at slide 61 -- warning: it's a large slide deck!). My JavaFX layout blog will also be updated soon to reflect changes in 1.2.
Starting simply, you can look at the container classes in javafx.scene.layout (Flow, Tile, HBox, VBox, Stack, and Panel). It's amazing how far one can get by nesting HBox and VBox. If you want the more sophisticated power of a grid style layout, you can use either Stephen Chin's Grid container or MigLayout (ported by Dean Iverson) in the JFXtras library.
6. Embed Swing Components Any Swing component can be embedded in a JavaFX scene graph using the SwingComponent wrap() function. This conveniently allows you to directly leverage those Swing components which you've already configured, customized, and hooked to your application data; all that Java code can remain happily unmodified. Once you've created the structure of your scene's layout, you can pull your Swing components into the appropriate locations. Here's a simple example:
The wrapped Swing component becomes a leaf node in the scene graph and as such can be manipulated like any other node -- rotated, scaled, skewed, made transluscent, etc. Through some hidden magic which transforms input events, the Swing component will just work, oblivious to its new 2D housing.
The limitation here is that the internals of the Swing component are not nodes in the scene and cannot be manipulated individually using JavaFX graphics ops. It's also worth noting that the entire Swing component can be made transulcent by setting the opacity variable on the wrapper, but this is not the same as having the Swing component's background be transluscent.
Another important restriction is that although FX script can freely invoke any of the Java apis on the Swing components, JavaFX script's language features (object literals, binding, functions) cannot be used directly with the component. This restriction can be mitigated by creating specialized FX classes which expose the Swing component apis as variables and functions. Many such classes are already provided in the javafx.ext.swing package (e.g. SwingButton) and the techniques for doing so are certainly worthy of another blog.
For our GUI Makeover client, we embedded a Swing JList and JTextArea, neither of which yet have pure FX counterparts. The JList already had a really nice custom cell renderer and we only had to modify the colors to better match the new visual design created by Jasper.
7. Hook up Listeners Although the magic of JavaFX's bind capability is not available on the embedded Swing components, it turns out to be easy to hook up appropriate listeners to those components within JavaFX script. In the GUI Makeover session, I showed how to create a JavaFX class which extends a Java Listener interface, however, after the session, Richard Bair showed me some syntactic sugar which makes this even easier:
8. Add Effects Now the fun begins. You no longer have to be a 2D mathematician to add effects like drop shadows, lighting affects, or box blurs into your interface. Chris Campbell has created the javafx.scene.effect and javafx.scene.effect.light packages in JavaFX that makes such visuals do-able often with just a single line of code. To mention just a subset....DropShadow, Glow, BoxBlur, Reflection, SpotLight. For GUI makeover, we put a reflection on our toolbar buttons:
You can achieve such effects in Swing (sans JavaFX) using clever Java2D imaging tricks, but the JavaFX language and scene graph capabilities make it vastly easier. What this means is that with very little effort you can experiment to explore what looks good rather than spending a bunch of time getting the math right to discover it wasn't what you wanted (I say this from personal experience :-).
9. Add Movement (but don't over-do it) Let's face it - the iPhone has raised the bar on interface design. The use of nice transitions to guide your users is now commonplace and expected. Obviously, as we proved with flying rockets in the Makeover session, animation can be taken too far (most engineers I know dream of being gamers) and I recently came across a blog post, flying pixels, which sheds some sensible light on the subject. However, adding subtle animation to give texture, guidance, and pleasure to your users is easy with JavaFX. The goods are in the javafx.animation and javafx.animation.transition packages. Timeline is the driver behind the general animation framework, however many common transitions are greatly simplified by using the canned transition classes, such as FadeTransition, RotateTransition, and PathTransition. In GUI makeover we added rollover effects to our toolbar buttons as follows:
And don't forget the rule of thumb that the best transitions are subliminal and arn't even noticed by your users.
10. Draw Your own Conclusions Skepticism is healthy -- especially in this internet age where we're all peddling something (technology, opinions, egos, tattered copies of The Mythical Man Month). But if you're a Swing developer looking to blend your Java code and skills with next-generation graphics, I'd encourage you to try JavaFX. You can even take your Java and Swing code with you.