Skip to main content

Insider's Guide to Mixing Swing and JavaFX

Posted by aim on June 10, 2009 at 5:47 PM PDT

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.


rocket3.png



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:

Stage {
    title: "Application title"
    width: 250
    height: 80
    scene: Scene {
        content: [
            Text { ... }
        ]
    }
}

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:

def swingTable = new JTable();
Stage {
    scene: Scene {
         content: VBox {
             content: [
                 SwingComponent.wrap(swingTable),
                 // other FX nodes
            ]
        }
    }
}

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:

     // appcontroller is instance of Java class maintaining various app model state
     // No explicit FX listener extension class required!
     appcontroller.addPropertyChangeListener(PropertyChangeListener {
            override function propertyChange(event:PropertyChangeEvent):Void {
                if (event.getPropertyName().equals("selectedMailBox")) {
                    // handle property change...
                }
            }
      });

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:


<toolbar3.png



def reflection = Reflection { fraction: 0.33 }; // effects can be shared!
composeButtonLabel = VBox {
     spacing: 4
     content: bind [
         ImageView {
             image: Image { url: "{__DIR__}resources/compose.png"}
             effect: reflection
             cache: true // caching good idea for static effects!

         },
         label = Text { ... }
     ]
}

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:

var label:Text; // label on toolbar button
var fadein:FadeTransition = FadeTransition {
    node: bind label
    fromValue: 0 toValue: 1.0
    duration: 100ms // fade-in is fast, don't want UI to feel sluggish
};
var fadeout:FadeTransition = FadeTransition {
    node: bind label
    fromValue: 1.0 toValue: 0.0
    duration: 500ms // fade-out is slower, like a trailing thought....
};

composeButtonLabel = VBox {
    content: bind [
        label = Text { ...
            opacity: 0.0 // label doesn't show until mouse-over
        }
    ]
    onMouseEntered:function(event:MouseEvent):Void {
        fadein.playFromStart();
    }
    onMouseExited:function(event:MouseEvent):Void {
        fadeout.playFromStart();
    }
}

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.

Related Topics >>

Comments

JavaFX composer based update ?.

Amy, Your blogs rock !!!. This is one of many articles and webcasts that I follow diligently. Could you consider updating this article with the latest changes in this area, namely the "JavaFX composer" tool?. I still need to write hybrid GUI's using JavaFX and Swing. Matisse/Swing and JavaFX/Composer are quite usefull RAD tools in this context. It would be really usefull for us to have the "10 commandments" in this scheme of things. Reading between the lines, it appears that awt/swing is being phased out ?. Is this accurate ?. A "position statement" of sorts would again be very very helpfull. Right now this space is filled with FUD. Much thanks again /rk

Hi, I'm doing a rework of an existing free application called Modellus (http://modellus.fct.unl.pt/) using JavaFX. It's mainly written on Java and developed on another IDE different from Netbeans. It has a portion that is beeing done in JavaFX using Josh's hack. The main problem is how do I debug that portion? I've tryed attaching the netbeans debugger but wasn't able to. Please can you help me? Pretty please?? :)

Amy, thanks! Its soooo good to hear that the integration all us "old school" swing developers are after is in the pipeline! Excellent - Happy Swing Developers Everywhere :D

@stevegal - your question (how to embed JavaFX in Swing) was the most commonly asked question at JavaOne, so I've added a paragraph at the top of the blog to address this. Internally we're well aware of the need here and I hope this is something we'll address in a coming release. In the meantime you can experiment with the hack documented in Josh's blog, but make sure to read through all the comments first :-).

Hi Amy thanks so much this was exactly what I was asking for at Java One!!!! The FX team and yourself are doing a bang up job and I can't wait to see what in store for us in the future :)

@stevegal +1

how can we add a javafx stage or scene into a swing app (can I provide a JStage or somesuch)? I've seen lots of examples of doing it the other way around - but this would be nice so that us Swing developers can add a bit of Javafx to our exisiting apps without having to access internal sun classes.

Hi Amy, thanks for the infos! While playing around with JavaFX there's one question which often comes to my mind: Why was it designed as a language? This seems to make things complicated for people who write JavaFX development tools (like the NetBeans JavaFX editor) and for developers who want to use JavaFX. To me, the way of Flex and Silverlight (XML GUI description with code behind file, using a well known language) seems to be a much easier approach for everyone: Existing tooling would be enough for a simple but supportive development environment. Developers would still have to learn about the possibilities of JavaFX but could stick to the languages they already know. Obviously the JavaFX language has some nice features like the integrated databinding, but these things are possible in plain java as well. So my question is: Why is the language approach of JavaFX considered to be more powerful than the way Flex and Silverlight are working? What benefits does the current solution offer compared to a combination of an XML GUI description and a Java code behind file? Thank you for clearing that up to me!

Whoops, I just found your answer to my comment on this subject in your last blog entry :-) I'm glad it's on your radar; please keep us up to date, even if it's just a more sophisticated hack. Now if you guys can just open up the JavaFX runtime distribution license so we can distribute it along with the JRE in our installers....

Amy - This is great for new small apps. But there's no way we can implement large apps in JavaFX. For one thing, those of us doing desktop app development have either adopted a large RCP framework like Eclipse or Netbeans Platform, or written our own. The language support, tooling, nothing is there to support large-scale development in JavaFX. Fabrizio summarizes some of our concerns nicely: http://netbeans.dzone.com/news/language-apart-what-i-miss That being said, I am totally on board with using a scenegraph-based UI, even for mundane things like forms. We already use Piccolo heavily in our app, and it is a vastly better way than Swing to make UIs. Can someone from Sun please provide some details on why it is so difficult to embed a JavaFX panel inside a Swing app running inside a standard Java main()?

Two big things are still missing: - as above embedding a JavaFx Scene in a Swing application - support for offline installation and distribution of the JavaFX runtime. (e.g. from CD)

Great article, Amy! @stevegal We are releasing a SceneToJComponent class that makes it easy to embed JavaFX Scenes in Swing applications as a part of the JFXtras 0.5 release. The final release will come out in a few days, but for now you can try out the beta here: http://code.google.com/p/jfxtras

Hi again Peter, To answer your question regarding javafx1.2, I haven't tried javafx1.2 yet. I'm using JFXtras and it isn't ready for it so I can't upgrade yet. That's really strange that no one else at Sun has mentioned and given another workaround for that. I hope you're able to fix that. If you do, please tell me something cause I was planning on upgrading to 1.2. Thanks, Pedro

Hi Amy, thanks for posting this. You won't believe how many positive comments we get on our swing business application just because it looks good. (Can you believe there were doubts applying java because of this;-) So we can't wait to embed javafx into swing to make it look even better! I hope you guys put priority on this, since it is the best way to increase acceptance for javafx. kind regards, Christiaan

Hi Pedro, > a run method on you scene class. Ah, okay now I understand. Thanks for that! So, my fix to josh's workaroung is not necessary. But still I am missing a workaround for javafx1.2. Do you have such a workaround? Or how did you solve it for Modellus? Regards, Peter.

Hi Peter, I mean that then you can use josh's workaround. I saw that in your blog you were complaining that you couldn't get it to work. On josh's blog I think he forgot to mention that you have to have a run method on you scene class. Regards, Pedro

Hi Dukke! What do you mean with that? Then I could call the javaFx run method. But then the scene is not embedded in my JComponent, right? Peter. PS: Josh's workaround does only fix javafx1.1. In javafx1.2 the JSGPanelSceneImpl class is missing...

Peter, Regarding your problems using josh's work around: do you have a run method on your javafx class that extends scene? You have to have one: public function run(args: String[]) { AnimationScene = AnimationScene { } // just an example } Regards

Hi Amy, I'm the author of [1], but now in JavaFx 1.2 there is no such JSGPanelSceneImpl class. Would you mind to give me a way how to use JavaFX1.2 in Swing? Also only a temporary hack or whatever would be very nice of you! Regards, Peter. [1] http://karussell.wordpress.com/2009/02/27/calling-javafx-from-java/

@realsnowbird "why a new language?" is a seriously good question. As I mentioned in my blog post, I was equally skeptical when Sun first embraced JavaFX script. Without getting into an academic DSL vs GP language debate (you can find plenty of those with a quick web search) I will just speak from personal experience. I can create a visually rich user-interface very rapidly using JavaFX script due to a combination of its language features (*binding*, sequences, functions) and the rich graphics/animation capabilities built into the scene graph. And the binding support in JavaFX is not the garden-variety binding framework you'll find in other environments (Java or Flex or Silverlight) - it's an extremely powerful expression-based binding akin to a programming power-drill (vs. a push-drill) (if you believe it's similar to what's offered in other environments then I can tell you haven't actually tried JavaFX yet :-). And the productivity gain comes in spite of the lack of decent tool support, a deficiency which we must remedy (I'm red in the face as I type this). In terms of comparing it to the XML GUI description with Java code-behind file, well in my opinion XML is just cumbersome -- all those angle brackets, quoted tag attributes, and code embedded with "

(from 1995, Self language defunct, but principles still relevant)" The Self language went through a quiet patch, but isn't defunct - download it for Mac and Linux at http://selflanguage.org