Here are some Swing links that you might have missed during this week:

  • Synthetica look-and-feel has released version 2.7.0 and 2.7.1. No new skins have been added, but there are some new features and bug fixes.
  • Swing has aged remarkably well considering its long history and imposed rules of preserving backwards compatibility. However, there are some trends in modern UI design that need some special handling in the application code, and Ken Orr shows how to address a common problem with tree renderers – making them fill the entire width of the row.
  • Phoenix addresses a few other shortcomings of Swing components, showing how to provide continuation tooltips on trees and lists, wider and resizable popup windows in comboboxes and more.
  • Tim Boudreau announces the availability of a pure tree table implementation available as a standalone module in NetBeans. I have seen a few such implementations, and they usually involve using an entire tree as the rubberstamp renderer for the tree column, translating and clipping the tree to show only the relevant part for each row. This presents significant maintenance problems in passing the events and having look-and-feel consistent animation events. Looks like Tim and Standa Aubrecht have been able to solve these problems. Geertjan Wielenga has a tutorial on how to use this tree table to show information on the file system.
  • Collin Fagan continues working on the Swing tutorials and this week he has code samples for trees and borders.
  • Alex Potochkin has announced release 3.0 of his JXLayer project. This is one of my favorite third-party additions to Swing, and it’s great to see that it is continuously improving. There is a brand new forum on java.net where you can ask questions on JXLayer, and i have found Alex to be extremely quick to respond and cooperative to address feature requests. We have also updated the Rainbow project to use the latest release of the library.
  • David Qiao has posted slides and demo source code for his JavaOne BoF session on working around Swing bugs.
  • Anthoney Scotney has announced release 4.2 of WebRenderer Swing edition, a browser SDK based on Firefox 2. The decision to base the code on Firefox is interesting, especially in light of other vendors (such as TrollTech and Sun) deciding to use the competing WebKit library. Firefox 3 is about to be released (perhaps sometime this week), and it would be interestingto see how quicky WebRenderer will switch. The performance improvements in Firefox 3, especially for JavaScript-heavy sites, are quite impressive.
  • Joe Conti has created a static analysis tool to detect EDT violations at compilation time. The CheckThread project requires annotating your methods with the name of the intended runtime thread, and then checks to see whether there are any clashes between methods.
  • Detangler is another tool that aims to detect Swing threading problems. It attaches to your application running in debugging mode and shows thread-related bugs that cause visual artifacts, gray windows, deadlocks and slow listeners that cause frozen UIs.
  • Vaibhav Choudhary proposes a tool that will convert existing Swing applications to JavaFX. I’m not sure if the comparison with GWT as savior to writing AJAX applications is relevant, but from my experience automated conversion from one language to another never results in clean and readable code. There are just too many small differences between any two given languages, and you either decide not to support this (requiring large amount of manual work for any nontrivial app), or end up with an inordinate amount of generated code that doesn’t look anything like the best practices for the target language.
  • Finally, Josh Reed has been experimenting with Groovy’s GraphicsBuilder, and he is very impressed.

A considerable part of the new skinning layer of Substance is geared towards enabling writing Swing applications that have UI capabilities of this WPF application designed by frog studio (mentioned a few months ago on this blog):

The required changes have slowly sipped into releases 4.2 and 4.3 of Substance, but were limited due to maintaining as much backwards compatibility as possible. However, the old skinning / theming layer was not up to the challenge, especially considering its deficiencies in handling mixed light / dark skins. This layer has been completely rewritten in version 5.0 (currently under development) and it is now possible to use different skins for different top-level windows (such as frames and dialogs).

To specify a custom skin for the specific top-level window, use the SubstanceLookAndFeel.SKIN_PROPERTY client property and set it on the root pane of that window. To get the skin of the specific control (to provide custom painting that is consistent with how Substance paints core and third-party Swing components), use the SubstanceLookAndFeel.getCurrentSkin(Component) API.

Here is a screenshot that shows an application with twelve top-level frames, each using its own skin (click for the fullsize version):

Note that applications using a single global skin do not incur performance overhead. Applications that use per-window skins do not incur performance overhead as well, but the memory consumption will be higher due to a larger number of cached images.

You’re more than welcome to test the latest development drop of Substance 5 and report any bugs (visual or exceptions) to the project mailing lists, forums on in a private e-mail.

Effective Java2D

June 6th, 2008

This post summarizes the changes that were made in Substance 5 to address the performance issues raised by the users. As mentioned before (part 1 and part 2), Substance 5 is 2.5-3.5 times faster than Substance 4.3 on various static and dynamic scenarios. Many thanks go to Dmitri Trembovetski from Java2D team for his help and tips.

  1. Use multi-stop gradients (LinearGradientPaint) with REPEAT cycle method (as mentioned in the comments on Romain’s blog entry).
  2. Rendering translucent texts is slow and does not use the new native font rasterizer in 6u10. Solution – instead of installing a translucent composite, interpolate the text foreground color and the background fill color based on your alpha value, and use full opacity text rendering.
  3. BufferedImage.setRGB and BufferedImage.getRGB are really slow. A custom BufferedImageOp might be more difficult to learn, but is much more performant if done correctly.
  4. Set RenderingHints.KEY_ANTIALIASING to OFF before calling any Graphics.fill operation that results in aliased fill in any case. This is especially relevant for Graphics.fillRect that gets integer parameters. Java2D is not smart enough (yet) to choose the non-antialiased path when the end result is non-antialiased.
  5. Intermediate non-cached BufferedImages are slow. Whenever possible, either draw directly on the Graphics context, or collect the final result into one BufferedImage that goes into the cache, even if the cache key is more complex.
  6. Filling with translucent color or filling under translucent composite is very expensive. In fact, the single largest performance gain (20% of the final result) in Substance 5 was removing watermarks from most core skins.
  7. Use AffineTransform for rotating painting instead of doing it manually. As with BufferedImageOp, it takes some time to understand how to do it (and i’m still terrible at it), but the performance is much better.
  8. Use EnumSet and EnumMap whenever possible. This is not Java2D-specific, and the tip goes to Joshua Bloch. These are quite faster than Hash* counterparts.
  9. Do not do multiplt rendering of the same surfaces. This is especially relevant for tables thatcan have potentially thousands of visible cells on the screen. Try to draw background fills and gradients once per table.
  10. Last, and not specific to Java2D – profile every scenario, question every method and every line of code.

More tips on Java2D performance right here.

Update: hitting “Submit” too fast, i forgot another Swing-specific optimization. Since everything UI-relates has to run on EDT, you can use non-synchronized non-thread safe code and collections. This comes in quite handy coupled with caching images and additional otherwise guarded blocks.

As i was looking at the directions to a store on Google maps, i noticed that they’ve added a new functionality to click on each route turn point and see the “street view” shots. Here is how one of the exits off highway 87 looks on Google:

CA 87 exit C1

and if you manage to find your way through the parking lot, you’ll just need to drive through another house to get to Santa Teresa:

CA 87 exit C1

Reminds me of an episode in “The Office” where the boss drove the car into the lake a couple of yards before the bridge, just because the GPS lady told him to :)

Update: deciding to go a little bit further to Santa Teresa, Google would like you to go against the traffic:

Santa Teresa fast and furious

and once you make it to the intersection, turn on red:

Santa Teresa fast and furious