Using SwiXML and Substance 5

by Rick Jelliffe

SwiXML is Wolf Paulus' XML User Interface languge (XUI or XUL) which uses the regularity of the Java Swing GUI libraries to allow very lightweight implementation: XML elements are used for JComponents, XML attributes are used for properties (e.g. <frame size="5"/> would be JFrame.setSize(5)), and there is provision for layout managers, ids, custom JComponents and so on. Substance is Kiril Grouchnikov's Look and Feel library for Swing components, which allows various subtle and lurid modern effects: the latest release, version 5, has just come out. Kiril has also written a good series of articles, available at his blog, on what he has learned about running a successful responsive open source project.

So, how can I use SwiXML with Substance 5?

Seelcting the look and feel with SwiXML is easy: you just add the appropriate plaf attribute to the top frame element. You can find a list of the various looks and feels available in Substance in the documentation or under the skin directory of the source tree. So your top element is, for example,


<frame plaf="org.jvm.substance.skin.SubstanceOfficeBlue2007LookAndFeel" ...>
...
</frame>


In many cases, that is all that is needed. However, I found a gotcha with an easy fix.

In Swing, you are supposed to do everything concerned with the GUI in the Event Dispatching Thread (EDT). This prevents some kinds of thread-related problems, for example where one thread tries to access an object already destroyed by another. Some of the Substance code has checks, which generate errors if the function was not invoked in the EDT.

However, all the example code from SwiXML is run straight from the main thread. This is OK in theory because you are just initiating the object so there is no chance of mishap.

The simple answer is to run the SwiXML initialization in the EDT, and invokeLater() is our friend here. Instead of


Component myGUI = new SwingEngine(this).render("xml/myGui.xml");

you use


Component myGUI;

SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
myGUI = new SwingEngine(this).render("xml/myGui.xml");
} catch (Exception e) {
e.printStackTrack():
}
}
}
Thread.yield();
Thread.yield();


Unfortunately, even though Substance is highly configurable, it mainly uses various kinds of system or UIManager or rootNode properties rather than setters. It is possible to make a home-made property element in SwiXML , however because Swing elements are initialized before being attached to their parents, there is no way to access the client properties of the intended target object, so it is not well suited. (It seems you may be better of just specify the look and feel mix you want in Java rather than SwiXML at the current time.) But the simple selection of Substance LAF seems to work fine.

SwiXML already has support for the JGoodies Forms library built-in, which some of the Substance demos also use. I hope to get around to using the Flamingo library with SwiXML soon.

What are those Thread.yield() calls? The first is to make sure that the EDT thread runs immediately, just because we want to be in a good known state. The second is because it is possible, though not likely (though in Java who can say?), that Substance itself may use invokeLater() calls on the EDT where the runnable will be cued on the EDT but scheduled after the return from the first Thread.yield(). The second call is at least harmless, and perhaps best practice: some people think that just because in Java you often don't have to think much about scheduling (or memory management) it means you never have to: quite wrong for desktop apps.