This post originated from an RSS feed registered with Java Buzz
by Danno Ferrin.
Original Post: Groovy, Verbosity, and Swing
Feed Title: And They Shall Know Me By My Speling Errors
Feed URL: http://shemnon.com/speling/archives/cat_GUI.rdf
Feed Description: Danno Ferrin's Many Reasons he was a Comp Sci Major and not an English Major
While I was on vacation in Hawaii Jonathan Simon lamented about how people still aren't getting it.. I think that the single biggest problem creating the misconception that swing is slow is that people don't understand or use threading on their GUIs. Two main problems exist. First any event you handle is inside the event dispatch thread which is also responsible for painting the GUI. Second, practically any manipulation of a JComponent must be done from within the event dispatch thread. Practically a paradox, but it can be dealt with.
Consider an action event that updates a label named jLabel with a string value from a long running method called takesTenSeconds. You may be tempted to do something like
public void actionPerformed(ActionEvent e) {
jLabel.setText(takesTenSeconds());
}
but then you violate the first rule: no long running calls in the event thread. With anonymous methods it can be handled however...
public void actionPerformed(ActionEvent e) {
(new Thread(new Runnable() {
public void run() {
jLabel.setText(takesTenSeconds());
}
}).start();
}
That's some progress. But we now violate the second rule: Don't use thread unsafe methods on JComponents or mess with models they use. In this case it will not be a problem, but when you start with JTrees, JTables, JLists, JComboBoxes, and the like you can create these lovely stack traces to system.out involving concurrent modification, null pointer, index out of bounds, and other stuff that looks bad to QA and clients. How do we fix this?
public void actionPerformed(ActionEvent e) {
(new Thread(new Runnable() {
public void run() {
final String newText = takesTenSeconds();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jLabel.setText(newText);
}
});
}
}).start();
}
A code snippet that a random VB developer would assume is one line morphs to 3 times it size in characters and (depending on your codeing style) 10 lines in the code. Even with another utility method for the background call we have to make two runnable classes, whether anonymous, inner, or stand alone that's a lot of code bloat. What would be nice is a more concise syntax for a runnnable. Enter Groovy and closures. This can be made much smaller with the creation of a few simple utility closures...
I think that the greatest problem with the swing APIs are not that they are too complex or too poorly explained. The biggest problem I see is that to do simple things the correct way, it can get quite verbose. Kind of like reliable file I/O, but you get far fewer urgent-1 bug in the GUI than in core I/O routines. Perhaps the best thing isn't to change the Swing APIs, but to add more syntactic sugar.