Subscribe to our mailing list

* indicates required
Close

Wednesday, April 08, 2009

Swing versus death by paper cut

The other night, I was looking at the JSR-296 Swing Application Framework prototype implementation, which is (according to the landing page) "a small set of Java classes that simplify building desktop applications." What made me smile is the statement (on that same landing page): "The intended audience for this snapshot is experienced Swing developers with a moderately high tolerance for pain. "

When I tweeted this, Gil Hova tweeted back: "Wait. There are Swing developers with low tolerances for pain?"

I laughed so hard I almost blew coffee out my nose. (Now that's taking Java seriously.)

Before going any further, I should tell you that the
Swing Application Framework appears to be dead (the JSR is marked Inactive), with the most recent build carrying a date of 19 October 2007. It was supposed to go into Java SE 7. But it now seems to be in a kind of limbo.

But in case you were wondering what, exactly, the Swing App Framework is designed to let you do, here's the Hello World example cited by the creators.
public class ApplicationExample1 extends Application {
JFrame mainFrame = null;
@Override protected void startup(String[] ignoreArgs) {
JLabel label = new JLabel("Hello World", JLabel.CENTER);
label.setFont(new Font("LucidaSans", Font.PLAIN, 32));
mainFrame = new JFrame(" Hello World ");
mainFrame.add(label, BorderLayout.CENTER);
mainFrame.addWindowListener(new MainFrameListener());
mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
mainFrame.pack();
mainFrame.setLocationRelativeTo(null); // center the window
mainFrame.setVisible(true);
}
private class MainFrameListener extends WindowAdapter {
public void windowClosing(WindowEvent e) {
exit(e);
}
}
public static void main(String[] args) {
launch(ApplicationExample1.class, args);
}
}
I'm sure there's a lot of goodness packed() away somewhere in the bowels of the SAF API, but it sure isn't showing up in this Hello World code.

If you run the foregoing code, you get:



Yes, it's an ugly large-type edition of browser-JavaScript's window.alert( ). Except it takes 20 lines of code instead of one.

This snippet illustrates a scant handful of the many annoyances that make Swing programming feel so much like death by a thousand paper cuts. For example, it shows the repetitive boilerplate code Swing programmers are forced to write every time something as common as a JFrame is needed. The setLocationRelativeTo(null), setVisible(true), the ever-ridiculous pack(), all are needless mumbo jumbo. Get rid of them! Roll them up out of view. Make them default behaviors. If I want to override these things, let me. But nine times out of ten, when I create a JFrame, I do, in fact, want it to be centered onscreen; I want it to be visible; I want it to go away when dismissed (and be garbage collected); and I don't want to have to recite pack() ever again in my lifetime.

A library that makes programmers write boilerplate is lame. It violates a basic principle of good API design, which is that any code that can be hidden from the programmer should be hidden. (See slide 28 of Joshua Bloch's excellent slideshow.) Not giving things reasonable default values is, likewise, a sin.

There's something else here that rubs me the wrong way, which is that if you're creating a new API (or framework, in this case) to supplement an existing API, it seems to me you shouldn't use that as an opportunity to introduce additional language syntax. In other words, don't introduce annotations if the underlying API doesn't use them. Keep it simple. Streamline. Simplify.

But enough ranting. On balance, I think the Swing App Framework is a good idea and adds value, and I think something like it should go into Java SE 7, because although it doesn't make writing JFrame code any less annoying, it does provide a host of application services that would otherwise require Swing programmers write tons and tons of really tedious code. Anything that reduces that tonnage is good, I say.

11 comments:

  1. Although I agree this example is plain stupid, I would say you didn't do your homework properly (and JSR-296 participants, if any left, didn't do theirs about giving a better 1st example).

    If you dig just a little further into it, you'll see that Swing App Framework brings much more than this and needs less coding than that: just have your example derive from SingleFrameApplication instead of Application and you'll see.

    About the tolerance to pain of Swing developers, although there is some truth there, that is not to such extent as you want to (make us) believe;-)

    ReplyDelete
  2. Thanks for the props, Kas! I'm still a newbie to Java in general and Swing in particular. But I've been learning Swing for the past couple of weeks, so your timing was serendipitous.

    It's funny that NetBeans' documentation insist that you should create complex Swing forms with the graphic interface, while users insist that everyone avoid the graphic interface at all cost.

    After a bunch of invisible labels and misaligned text boxes, I sided with the users.

    ReplyDelete
  3. Anonymous11:28 AM

    How do you propose "pack()" without actually calling it? It's a bit like saying "hey swing thing, I've finished adding stuff, please lay them all out nicely". By removing the call, the frame can't know when it's safe to squash things down.

    If setVisible(true) was the default, then the frame would appear immediately even if you wanted setVisible(false) to be the behaviour. The little gap between new JFrame() and setVisible(false) would have that frame visible. This could be a disaster if, for example, you want to draw the widget to an off screen graphic. In a headless environment that would cause an exception e.g. no X on Linux. A typical use case is a server version of your app that can be used just to print stuff out.

    APIs are tough to get right. If you think Swing is bad, try JFace or its evil underling SWT.

    ReplyDelete
  4. "It violates a basic principle of good API design, which is that any code that can be hidden from the programmer should be hidden."

    I'm not sure that I agree with this 100%. I'd say something more along the lines of "anything that is commonly unnecessary but still helpful and not dangerous should be bypassable but not unavailable."

    ReplyDelete
  5. @Anonymous:
    That's just stupid... Saying something is not bad because it sucks less than something else?

    I have never done any work in Swing, so I don't know the details, but it doesn't seem like something impossible. You could either use another constructor, that returns an invisible frame, or let the user us static factory methods. It's not impossible to create a user-friendly API, that still allows you to tweak it to your liking, if you just work at it.

    ReplyDelete
  6. It would be interestingto see what an ideal API would look like to you: what would you want to type, instead of those 20 lines, to achieve the same effect?

    ReplyDelete
  7. Here is what I would change:

    1. Remove the need to register for the closing window adapter. Make that default, unless you override by alternate constructor call.

    2. Make setLocationRelativeTo(null) and pack() default operations as well.

    3. Consider a callback option, where actually construction of the JFrame is handled elsewhere, and you just plug in the important stuff:

    public class MySwingApp extends SwingApp {
    ..../**
    .....* setLocationRelativeTo(null), setVisible,
    .....* and defining default closure policy
    .....* is all handled inside SwingApp.
    .....* It should be bundled into a another
    .....* extension point, allowing either
    .....* override by constructor or by overriding
    .....* a key protected method.
    .....*/
    ....@Override // abstract method impl
    ....protected void addParts(JFrame frame) {
    ........JLabel label = new JLabel("Hello World", JLabel.CENTER);
    ........label.setFont(new Font("LucidaSans", Font.PLAIN, 32));
    ........frame.setTitle("Hello World");
    ........frame.add(label, BorderLayout.CENTER);
    ....}

    ....public static void main(String[] args) {
    ........new MySwingApp().launch();
    ....}
    });

    Other key lifecycle points could also be extended. If you need to keep a handle on the JFrame, you can grab it immediately during the callback.

    ReplyDelete
  8. Anonymous4:48 PM

    Gui implementations in Java have just been horrible.

    AWT - Ugh! Write once debug everywhere!

    Then Swing came along and I was like ZOMG this is even worse (let alone the threading issues), its like shooting an ant with a cannon!

    Being a real time graphics / game focused kind of developer I soon realized that Any pre-rolled solution from Sun was never gonna cut the mustard in real time interfaces, in fact they are so far off its laughable.

    SWT looked interesting, but by then I had "written my own Gui / User event processing model" from the ground up, it runs many times faster, doesnt even take 100k of classes and can be dynamically reloaded realtime. I even wrote it to not use as much of "java's" code as possible so it can be "easily back to ported to C or C# or any other language that I will move to next so I could 'future proof' my investment of time / effort / code".

    Basicly the Java gui solutions where the first example of the "Vista" syndrome.

    Takes 100x the memory and processing power for x1.2 the gain in look and usability.

    Where did all that memory and processing power go and you gained what? LOL!

    I wasn't surprised tho looking and how Obese J2EE is.

    I follow the KISS principle when it comes to writing software

    Keep It Sweet & Simple.

    :-)

    ReplyDelete
  9. Steve W10:17 AM

    I use it day in day out and have no problem with it ! It's simple to use and very quick to prototype to customers. I've used other systems for gui development and they are either so simple to code they aren't really flexible or so hard to code they are verging on unusable, however flexible they are. I think Swing sits somewhere in the middle and apart from many many short falls in what it doesn't so I think its basically fine.

    ReplyDelete
  10. we provide a power leveling and free wow gold wow power leveling|*|wow power leveling|*|http://www.wotlk-powerleveling.com|*|fdgf51

    ReplyDelete

Add a comment.