1 2 3 Previous Next


39 posts

  I've made a prototype of the fledgling JSR-296 API available,   it's     https://appframework.dev.java.net/.    There's a quick overview doc and downloads of the source code,   the javadoc, and the AppFramework.jar file.  If you're   interested in this API, please take a look at the overview, and   download the code and then take a look at some of the examples   and the javadoc.  You can post feedback here or, if you want to   participate in the long-term discussion, subscribe to the   appframework.dev.java.net "users" mailing list:       https://appframework.dev.java.net/servlets/ProjectMailingListList   .    The users alias is the last one listed.

  That's all I really wanted to say.  I don't want to make too   much of a commotion about this version of the design because   there's still quite a bit that remains to be done.  I was hoping   that this would be a sort-of stealth release: not   terribly noticeable, unless you know where to look.  On the   other hand, I know there are Swing developers who aren't members   of the JSR-296 expert group, who'd like to take stock of where   this project is going.  And I know there are experienced Swing   developers out there, some of whom have built their own   application frameworks, that would like see how this one   measures up.  I'd welcome feedback from anyone who's interested   and I'll promise to respond promptly, unless you bring up a   really difficult issue or a really large number of them.  That   might take longer.

  Note also: the JCP defines a milestone called "Early Draft   Review" that means the expert group thinks the spec is complete   enough to begin fine tuning.  We have not reached that milestone   yet.

      Having written, by conservative estimates, about a jillion Java       Beans classes over the years, I have to say that I'm amazed that       we'd seriously consider changing the Java language to trivialize       this kind of Java Bean property.  It certainly is a property per       the spec, a read/write property at that, but - as a Swing       developer - it's the kind of property I almost never write.  And       if repetitive boilerplate is what we're hunting with this       language change, then we're shooting at rabbits while a herd of       buffalo thunders by.  The mighty buffalo of the Java Beans       boilerplate animal kingdom are bound properties.  They're the       kind of properties we write so that our beans can be       automatically and dynamically synchronized with a GUI or with       each other.  As a desktop developer, I almost always write bound       properties.    


      To write a bound property properly you've got to ensure that       your class defines or inherits support for a       PropertyChangeListener.  That's about 20 lines of code just to       get started:    

class FooBean {
    private final java.beans.PropertyChangeSupport pcs;
    public FooBean () {
     pcs = new PropertyChangeSupport(this);
    public void addPropertyChangeListener(PropertyChangeListener listener) {
    public void removePropertyChangeListener(PropertyChangeListener listener) {
    public PropertyChangeListener[] getPropertyChangeListeners() {
        return pcs.getPropertyChangeListeners();
    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
        pcs.firePropertyChange(propertyName, oldValue, newValue);


      And then there's the definition of each read/write property       which should: check the validity of new values in its       set method as well as calling firePropertyChange to notify       PropertyChangeListeners, and defensively copy the return value       (if necessary) in its get method.  I suppose one could       concoct syntax that would simplify all of this, at least a       little, as well as allowing for read-only/write-only variants.       But that's not the proposal I wanted to make here.    


      If you consider the property keyword proposal in light of Java's       origins in the C language, then it's pretty clear what the       proposal's proponents are really after: structs.  It's not       about defining properties, it's about simplifying defining a       Java class that's comparable to a struct in the C language.  So       perhaps the proposal should really focus on allowing one to       write classes, not properties.  Where this:    

struct FooBean { Foo foo; }
    Would by equivalant to this (as before):    
class FooBean {
    private Foo foo; 
    public Foo getFoo() { return foo; }
    public void setFoo(Foo foo) { this.foo = foo; }


      If you admit that the focus of the property proposal is really       adding support for defining structs in Java, then using "->" to       refer to struct properties feels like coming home again.    

struct Point { int x, y; }
Point p = new Point(); 
p->x = p->y = 0; // oh joy

      I'm not a language design expert however I would think that I       would be among the target developers for Java language feature       designed to support properties.  In my humble (ha) opinion, the       current proposal serves the needs of Java Beans developers       poorly by targeting a special case that doesn't warrant language       support.  Although I would welcome a proposal that also simplified       defining bound properties, I would guess that it would be hard       to invent syntax that would handle the general case without       being obscure.  If there is a consituency for the current       proposal, I say: give them structs instead.    

Hans Muller

Dialog Diatribe Blog

Posted by Hans Muller Oct 27, 2006

  I've been writing the occasional small application recently and   now and then I blunder into a problem with Java SE that's,   uh..., well, annoying.  I realize that I'm not the only one   who's had this experience and I'm probably not the only one who   seeks relief by writing a lengthy diatribe and then sending it   to whomever might be guilty of creating the situation.  Of   course, in my case that's often me, and since relief usually   doesn't come from berating oneself, I'm guilty of sending the   occasional long crabby missive to the people who are currently   responsible for maintaining things that I'm probably responsible   for bollocksing up in the first place.  It's not a particularly   endearing habit.

  I sent the following to Swing's technical lead,   Shannon     Hickey, and he confirmed that the details, though twisted   with bile, are essentially correct.  So in the interest of   furthering my own therapy, and also to ensure that some record of   this will be stored away in Google's indices till the end   of time, I thought I'd share.

  I would think that a fairly common idiom in a Swing application   would be to popup a dialog in response to selecting a menu item.   Given Matisse, we'll   assume that the JDialog has been created with the IDE, rather   than some JOptionPane convenience method, and given rudimentary   aesthetics, assume the dialog should be centered over the menu   item's frame.  Accomplishing this seems to be much too   difficult:

public void showMyDialog(ActionEvent e) {
    // How to find the Dialog's Frame owner?
    Window dialogOwner = null;
    JDialog dialog = new MyDialog(dialogOwner, true); // true => modal Dialog
    // How to center the Dialog?

  The first problem to deal with is mapping from the menu item's   ActionEvent to the frame that contains the menu item.  The   frame will be the dialog's owner as well as the component we're   going to center the dialog relative to. 

  There seems to be an overabundance of SwingUtilities methods that   address this trivial problem:

  • Window getWindowAncestor(Component c)
  • Window windowForComponent(Component c)
  • Component getRoot(Component c)
  Sadly, none of them "work" for a JMenuItem.  They all simply   traipse up the parent chain and in our case they find a   JPopupMenu and then null.

  To find the Frame that owns a JMenuItem, we have to follow the JPopupMenu's       "invoker" property, which gets us back into the component   hierarchy.  So to find the frame that corresponds to an ActionEvent   one must write (!):

Frame frameForActionEvent(ActionEvent e) {
    if (e.getSource() instanceof Component) {
        Component c = (Component)e.getSource();
        while(c != null) {
            if (c instanceof Frame) {
             return (Frame)c;
            c = (c instanceof JPopupMenu) ? ((JPopupMenu)c).getInvoker() : c.getParent();
    return null;

  It would more useful to have written   windowForActionEvent but sadly support for   creating Dialogs whose owner is a Window (the parent class for   Frames and Dialogs) only appeared in Java SE 6, and I needed   code that worked for Java SE 5.  It's also worth noting that   this works for Applets too, although you'd be forgiven for not   guessing that this is true.  Applets do have a Frame parent   that's created by the Java plugin and whose bounds are the same   as the Applet (Panel) itself.

  But we're still not done, because we must also center the dialog   over the frame.  Naturally there are other useful positions for   the dialog.  Centering a dialog over its frame happens to be what   started me on this quest.

  I have it on good authority that       Windows.setLocationRelativeTo() is the handy method for     this job.  The javadoc for this method isn't promising:

      Sets the location of the window relative to the specified     component.  

  OK so far.  Except it sounds like I'm going to have to compute the   relative origin of my dialog and deal with edge (of the screen)   conditions.  Yech.

      If the component is not currently showing, or c is null, the     window is placed at the center of the screen. The center point     can be determined with GraphicsEnvironment.getCenterPoint     [sic]  

  Huh?  What does "the component" refer to in this sentence?  I   assume they're not referring to this Window and I have to   wonder what "showing" means in this context.  Is is the same   thing as getVisible() being true?  If not, do I   have to hope that my menu item is still "showing" when this   method is called?  And what's this advice about   getCenterPoint (and where's the period)?  In my   case the Window and its menu item are visible, so I'm hoping   none of this stuff applies.  Because I don't really understand   it.

      If the bottom of the component is offscreen, the window is     placed to the side of the Component that is closest to the     center of the screen. So if the Component is on the right part     of the screen, the Window is placed to its left, and visa     versa.  

  This, no doubt, means that the method will endeavor to find a   location for my dialog that respects the relative location I've   specified, without making part of the dialog appear off-screen.   Good, I think.

  So I still appear to be stuck with computing an origin for my   dialog that centers it relative to its owner.  Before I code   that, I try leaving the origin of the new dialog at 0,0, which   is the default:

public void showMyDialog(ActionEvent e) {
    Window dialogOwner = frameForActionEvent(e);
    JDialog dialog = new MyDialog(dialogOwner, true);

  Miraculously, this works.  The dialog appears centered over the   dialogOwner unless that would cause the dialog to appear   off-screen. I have no idea why it works, since according to the   "spec" (and the name of the method) I should have had to compute   an appropriate relative origin for the dialog.  But I guess I   don't.

  Frankly, I think this whole mess is a mini-travesty.  If I'm   going to show a dialog, I should be able to do so without   writing code that digs around the component hierarchy and   without experimentally determining what something as simple (and   not terribly useful) as Window.setLocationRelativeTo() does.

  There, that feels a little better.

  A   seven year old bug that covers the menu item to frame lookup   problem is still open.  Given the fact that it's accumulated   exactly 0 votes in that time, perhaps no one has ever cared about   the problem quite as much as I do at this moment.  I would think   that a cleaner way to handle this case would be some static   methods that handled the entire idiom, for example:

public void showMyDialog(AWTEvent event) {
    Window dialogOwner = Window.eventToWindow(event);
    JDialog dialog = new MyDialog(dialogOwner, true);
    Window.showModalDialog(dialog); // Center dialog relative to its owner

  And Shannon suggested that the method name might be rationalized   as implying that the Window is be moved to a location that makes   its relationship to the component parameter obvious.   Typically that means centering the Window relative to the   component.  In return for that tortured explanation, I had to   agree to file an RFE about the   Window.setLocationRelativeTo() javadoc.  I haven't   done so yet.  But I will.

   Thanks for listening.

Tuesday morning this week, I was seated in the vast Moscone keynote cavern, with 15,000 other Java developers, taking in the start of another JavaOne conference.  The keynotes and demos were entertaining and I hope you didn't miss the HUGE Swing Aerith demo at the conclusion of the morning.  Sadly I did, although I've seen quite a lot of it over last few weeks.  I had to dart out early, because my first-ever JavaOne musical gig started at about 10:30 and I had to get my bass and set up in time for the big Dukelele show.

That's right, Dukelele.  A Ukelele painted like so:


A group of us played music in front of the JavaOne store at one end of the corridor that connects the Moscone's North and South subterranean chambers.  In addition to me, the band was Hideya Kawahara and Yuichi Sakuraba playing Ukeleles (Dukeleles!) and singing, Mark Anenberg on a guitar-shaped drum synthesizer, Chet Haase on a laptop powered keyboard, and Kaoru Nakamura playing a keyboard/harmonica hybrid called a Pianaca.  And to top if off, Duke danced and hugged people.

We started playing as the keynote audience began flooding past and to our delight, many of them stopped to listen.  Tragically, the Moscone Fire Marshall did not share our joy.  After about 10 minutes he swooped in and put a stop to the show.  I guess we were a fire hazard, or at least Hideya was.  He was really putting his heart into singing and playing and I suspect that the Fire Marshall was afraid that he might suddenly burst into flames.

Another rock and roll show, shut down by the man.  Not exactly Altamont Speedway, but definitely a strange and abrupt ending to our little performance.  Fortunately one of our colleagues videotaped the whole thing and so now you can check it out on YouTube.com.  No animals were harmed in the making of this video. 

We played again, in the afternoon, outside on the sidewalk.  It was a bit breezy and most of the people who drifted by gave us an odd look and then slipped indoors.  One was exception was Tim Boudreau, who took in the entire set and then threw a quarter in our tip jar. Except we didn't have a tip jar.  Our friend the Fire Marshall seemed to be pleased that we finished without spontaneously combusting. Cautious man that he is, he kept a sharp eye on the proceedings from a safe distance, clutching his fire extinguisher in one hand, and a fistful of swag from the Motorola booth in the other.  Next year we'll bring our own fire protection.

One aspect of many docking GUIs is support for reconfiguring tiled subwindows by dragging shared subwindow edges.  MultiSplitPane and MultiSplitLayout support arbitraily complex tiled layouts that can be reconfigured interactively and programatically.

As introductory paragraphs go, the previous one has to set a new record for "not catchy".  It always seems easier to start these things with a personal story or recollection.  So how about this:

Earlier this year I was arguing with Tim Boudreau about docking frameworks and how best to compute an initial layout, when it occurred to me that a tree structured model would be a nice way to encode the relative sizes and positions of the tiles.  If nodes in the tree corresponded to tiles arranged in rows and columns, and if tiles were allocated space proportionally, it seemed like only a small project to build a two dimensional analag of JSplitPane.  Tim suggested that my project estimating skills were suspect and besides, there were more important things to do.  He was right on both counts, and yet. Sometimes, when you're orbiting around an idea, headed somewhere else, you find yourself captured by the idea's gravitational field.  As it turns out, I was in the software-idea equivalent of a tractor beam.

Over the next two days, I implemented the idea.  Since subwindow tiles were always allocated a fixed percentage of the available space, it was easy to write a recursive layout algorithm that arranged the rows and columns.  As I was just finishing up, Josh Marinacci dropped by, and so I proudly demo'd my creation.  The nice way to respond to someone's new demo, on Friday afternoon, is to smile, deliver a bland compliment, and suggest that it's time for a cold one.  Josh said: "that's nice, but I don't think anyone would really want to use it". After I stopped crying, he pointed out that people expect subwindow tile boundaries to stay put when the window is resized.  This is true, and it makes the problem substantially more difficult.  It means that growing and shrinking the layout aren't symmetrical, and it implies that the layout should honor preferred tile sizes, until the user has indicated otherwise by dragging an edge.  So, with tears in my eyes, I started over again.

Version two of the layout algorithm took considerably longer than the original version.  The result is the aforementioned MultiSplitPane and MultiSplitLayout classes, a small set of demos, a smattering of unit tests, javadoc, a nod to accessibility (more on that later), and an article that explains how it all works.  The article bows today on java.net, it's called MultiSplitPane: Multi-Way Splitting Without Nesting.  I hope you'll find the time to read it.  The classes will become part of the SwingLabs project now and perhaps be incorporated into a future Java release.

Every now and then someone drops by to ask about the slick chat/IM demo components that were shown in the Extreme GUI Makeover JavaOne session last year.  The Swing components created for those demos where hacked together in order to show what's possible and sadly, they're not available as production quality components just yet.  I certainly like the idea of resuable, configurable/extensible, chat client GUI parts.  If I were building that kind of application I'd be happy to avoid starting from scratch.  This blog is a brief look at one such part.  You can try it out by pressing the launch button.

             BuddyList demo screenshot                  http://www.java.net/download/javadesktop/blogs/hansmuller/buddylist/screenshot.png      
     BuddyList Demo Screenshot      

BuddyCellRenderer is an attempt to build a somewhat reusable JList CellRenderer for Chat/IM buddy lists.  It's job is to render an object that represents a Buddy roughly like this:

            screen name
     [status]  short message   [icon]

Here "status" is one of online, offline, or away.  Away status means that the user is online but busy.  The "screen name" is the Buddy's name, "short message" is an optional short message from the Buddy, and icon is a picture that represents the Buddy.  All of this is quite conventional.  These elements appear in most chat/IM application buddy-lists in one form or another.  If a "short message" isn't provided we change the layout just slightly:

     [status] screen name [icon]

The BuddyListCellRenderer must also provide a Buddy-specific tooltip that's displayed if the user lingers over one BuddyList element. 

JList renders list elements or "cells" by delegating to an implementation of ListCellRenderer.  ListCellRenderers have only one method, getListCellRendererComponent(), which returns a Component that the JList uses to paint a single list element.  The JList really just uses the cell renderer component's paint() method to draw or "rubber stamp" a list element.  The getListCellRendererComponent() method is passed the JList model's "value" for each list element, and its responsibility is to return a component that's been configured to display that value. 

The default ListCellRenderer is quite simple.  It just uses the same JLabel for every list element, roughly like this:

JLabel label = new JLabel();
Component getListCellRendererComponent(JList l, Object value, ...) {
    return jLabel;

To display the properties of a Buddy in the way we've layed out above will require more than just a JLabel.  BuddyCellRenderer uses a JPanel with subcomponents for the various properties and GridBagLayout to define the layout.

A generic ListCellRenderer that configures our JPanel composite to display a Buddy value is difficult because we don't want to dictate the type of the Buddy object but we do need to extract its status, screen name, icon, and message.  What's needed is an adapter that extracts the properties needed by the BuddyCellRenderer from the app-specific Buddy object.  The BuddyListCellRenderer.Adapter class does this.  The way it works is easiest to explain with an example.  Lets assume that our chat/IM application has a Buddy class that looks like this:

class MyBuddy {
    boolean isOnline() { ... }
    boolean isAway() { ... }
    String getScreenName() { ... }
    ImageIcon getIcon() { ... }

A JList ListModel that encapsulated the list of MyBuddy objects would have to be created; I will not delve into that here.  The adapter for MyBuddy objects could be defined and used like this:

class MyBuddyAdapter extends BuddyCellRenderer.Adapter {
    private MyBuddy getBuddy() { return (MyBuddy)getValue(); }
    public String getName() { return getBuddy().getScreenName(); }
    public String getMessage() { return getBuddy().getMessage(); }
    public ImageIcon getBuddyIcon() { return getBuddy().getIcon(); }
    public Status getStatus() { 
        if (getBuddy().isAway()) {
            return Status.AWAY;
        else if (getBuddy().isOnline()) {
            return Status.ONLINE;
        else {
            return Status.OFFLINE;

BuddyCellRenderer cellRenderer = new BuddyCellRenderer();
cellRenderer.setAdapter(new MyBuddyAdapter());

That's pretty much all there is to it.  The BuddyCellRenderer scales (and caches) the Icons provided by the Adapter if they're bigger than BuddyCellRenderer.getBuddyIconSize(). It also caches the "grayed out" version of the icon that's used when a Buddy's status is offline.  Alternating rows are rendered in an off-white color to help with readability and the whole thing is layed out internally with the old Swing layout veteran: GridBagLayout.

If you'd like to try making some changes to BuddyCellRenderer and the demo, you can download a NetBeans project with the source code and the jar files here: Download BuddyList NetBeans Project .

About six months ago I had a dream.  Not the sort of dream that makes you wake up shrieking or smiling, and not the kind that brings you down from the mountain top or even gets you off the couch.  Mine was the kind of dream programmers have.  The kind of sloth inspired idea that comes to you while staring at the screen, wondering if there's a way to eliminate all of the mouse clicking and key pressing effort that makes you weary without actually burning calories.

I spend quite a bit of time looking at Java blogs and articles that incorporate lots of source code.  Usually there's a link for zip file that contains all of the files the document refers to, and maybe a jar file with a build.  Sometimes articles include direct links to source files, however scanning a pile of source code with the web browser isn't terribly appealing.  The nicest way to look at code and try out APIs, is to just load everything into a Java IDE like NetBeans.  Once that's done it's possible to use the editor and debugger and all of the other IDE features to explore the code.  Like a real programmer should.  And just like a real programmer, I'm usually too lazy to bother.

So the big idea was to write a web started app that would download a complete NetBeans project, launch NetBeans, and open the key source files in the editor.  That way, if someone was reading a blog or an article about some Java project, they could click on a JNLP link - and with no additional effort! - peruse the code from within the IDE.  To me, this seems like a civilized way to do business.  Sadly, I wasn't able to con one of my colleagues into building such a web started app. Towards the end of last year, as Sun began to slow down in anticipation of the Christmas break, I took a crack at building a NetBeans launcher.  You can try it now, by clicking on the handy launch button below.  It's a signed application, because it creates a temp file and launches a (NetBeans) process on your machine, so you'll have to click through a security dialog.

To give the example launcher a try, just click the Launch button:

Web started application launch button

The launch app depends on the NetBeans OpenFile module to start the NetBeans IDE, if necessary.  Sadly (at the moment) there isn't an "OpenProject" module, so the best I can do is to show a single Java source file.  If the launch app is unable to locate an installed copy of NetBeans, it displays a little form that allows choosing the install directory, or downloading the current NetBeans release. I haven't tested launch very carefully (works on my machine :-) which is unwise, since part of the code to find and launch NetBeans is platform specific.  It should work on Windows XP and it might work on Linux or the Mac or Solaris.  I'd be happy to hear from anyone who's tried it.

The example file downloaded by the launcher, NetBeans.java, deals with figuring out if and where NetBeans is installed.  I didn't pick this one file out of pride, it's incomplete and contains some moderately embarrassing hacks.  On the other hand, it does all of the important work.  The class is used like this:

NetBeans nb = new NetBeans();
if (!nb.isInstalled()) {
    // give the user the opportunity to choose
    // the install directory or download NetBeans
else {
    File file = new File("C:\MyProject\src\pkg\MyFile.java");
    try {
    catch (NetBeans.Failure e) {
        // report the problem to the user

The initialize method uses some shameful heuristics to try and figure out where NetBeans was installed.  Check out the source code from within the IDE to see what I mean.  It would certainly be much nicer to be able to look in a well known (per platform) place to find out what versions of NetBeans were installed and where; maybe in the future that kind of support will emerge.

You can use the launch app on you own web site, just by making a copy of the JNLP file file and replace the URL in argument element at the bottom. The current version links to the example NetBeans.java file:


You don't need to copy the launch jar files or anything else.  Just create a link to your version of launch.jnlp on your site, and make sure your web server is configured to support the JNLP MIME type.

This was originally intended to be a quick project that I'd finish on on the long flight home from Prague back in December.  It didn't turn out that way, in part because building (usable) GUIs is always more work than you'd think.  It's also because I took the opportunity to get introduced to Matisse.  It's been a long time since I've been comfortable writing Swing GUIs with a tool.  Using Matisse turned out to be pretty inspiring: it worked well and it greatly simplified the task of evolving a GUI. Using it was a constant reminder of all of the additional desktop app building support that should be in NetBeans.  More about that in another blog.

I have a long laundry list of worthy improvements for the NetBeans launcher.  I'd be interested to hear what other developers think of it and what you-all think should be changed/improved.  Here are a few of TODO items from the top of my list:

  • Download a complete project packed into a jar file and expand that into a temp directory.  Open a set of project relative source files in NetBeans.
  • Log errors, and warnings and provide a way to show them.
  • Show the main window roughly in the middle of the screen. And wouldn't it be nice to know which Screen NetBeans was already running on - if there were multiple screens.
  • An "OpenProject" NetBeans module.  I've been assured that this wouldn't be so difficult to write.  Making sure that it was deployed to the IDE, before the project was launched would be a bit of a trick.

If you'd like to look at the complete NetBeans launch project, you'll find a zip file of the complete project here.  I realize that it's more than a little ironic to publish such a link.  Hopefully I'll be able to support loading entire projects (not just files) in round two.

It's my fault.  The fact that adding a component to a JFrame required one to explicitly add it to the JFrame's "contentPane" is my fault. Early on in Swing's evolution we added a runtime exception that warned developers not to write JFrame.add(myComponent) and it has been raising hackles ever since.  Graham Hamilton covered my transgression in his My Favorite (Dead) Java Boilerplate blog and I thought I'd explain the rationale behind it's birth and eventual demise.

It turns out that I did not create this trip-wire to incite violence or to "educate developers about the choices" within the JFrame container. JFrame's automatically created rootPane, layeredPane, and contentPane substructure was designed to enable popup effects that appear on top of the main GUI.  The original motivation for JFrame's substructure was we to support lightweight menus and tooltips and even dialogs that appeared within a top level window. It's also possible to use the substructure to produce novel GUI effects, like translucent full-window progress monitors. So why did JFrame.add() generate an exceptional slap in the face for the developer who's not schooled in all of this?

The 1.0 and 1.1 releases of Swing were delivered on the original Java 1.x platform.  Our audience was AWT developers who typically wrote small apps by subclassing java.awt.Frame and overriding paint() or setting its layout manager and adding children.  When we decided to create JFrame's substructure there was a debate about the wisdom of automatically mapping JFrame.add() to JFrame.getContentPane().add(). The reason I rejected that approach is that this "convenience" is a shallow illusion.  To complete the illusion one would have to redirect get/setLayout(), and addComponentListener(), and getComponent() and getChildren() and so on.  In addition to making it tough to actually get inside the JFrame itself, the complete illusion would be asymmetrical since the source of events or a layout manager's container wouldn't match what a developer would expect.  So in the interest of consistency, not education, we did not automatically redirect JFrame.add() to the content pane.

Time has passed and the number of AWT developers who's expectations might have been violated by making JFrame.add() convenient has become pretty small.  It's also true that the merits of providing a simple trouble-free out of the box experience, even if it depends on an imperfect illusion, are increasingly important.  So, in Tiger, JFrame's add and setLayout (and addLayout) methods have changed to "do what you [probably] mean".  The other JFrame methods, like getComponent(), do not redirect, so if you use them, be careful.  And if you don't use them, well, ignorance is bliss.

Now that we've got that out of the way, anyone have a nomination for a new Swing boilerplate hall of shame candidate?  As far as I know, the rest of the API is perfect.

I've been trying to think of a way to humbly announce that no lesser authority than Evans Data Corporation has reported that Swing is the dominant GUI Toolkit for Northern American developers.  It's difficult to present this new statistic with the grace and humility of good sportsmanship because, after nearly 8 years of steady growth:

"Java Swing with 47% use, has surpassed WinForms as the dominant GUI development toolkit, an increase of 27% since fall 2004."

That's a direct quote from the Spring 2005 report.  You may want to read it again (I have).  There are more developers building applications using Swing and Java SE than WinForms and .NET.  Despite the titanic resources marshalled by Microsoft to assert dominance over their own desktop platform, the Swing community has grown into an unstoppable force.  Microsoft has often been referred to as an "eight hundred pound gorilla".  Thanks to the persistence and enthusiasm of Swing developers everywhere, we've thrown the gorilla and the cage off the island.  We're the new alpha male, we're the King Kong of GUI toolkits.  We are the force to be reckoned with.  We are number one!.

I realize that was a little over the top.  I'm supposed to be humble and quietly confident about our success and not indulge in all of this vulgar gloating and boasting and jumping up and down on the desk shouting, we're number one, we're number one, we're number ...

Sorry about that. 

I'll just remain calm from here on in.  You'll have to trust me when I say that I'm reporting the following from a peaceful and serene perspective.  The use of both Swing and AWT have grown dramatically in the last year and, quoting from the report, "Java GUI development is clearly experiencing substantial growth".  So it is.  I would guess that there are at least two trends at work here.  People are writing Swing clients to augment or replace browser clients for network services, and developers really do care about platform portability. Sometimes portability is just about spanning different versions of Windows but more often than not, it's about covering the growing "alternative" desktop market.  Users want applications that provide entertainment or communication or educational experiences that are worthy of the fine computer hardware they're seated in front of, and the zippy internet service they're connected to.  Developers are choosing Swing to deliver those experiences and here, at camp Swing headquarters, we couldn't be happier. 

It's good to be king and it's hard to be humble.  I feel a T-shirt coming.


Thanks to Jeff Dinkins for another bit of just-in-time artwork!

Filter Blog

By date: