G$D/Groovy: Basic SwingBuilder

by Marc Hedlund

(For an overview of the G$D/Groovy series, see <http://www.oreillynet.com/pub/wlg/5789>.)

Basic SwingBuilder



Groovy contains an excellent set of features called GroovyMarkup. The basic idea of GroovyMarkup is to make it easy to create nested hierarchies of objects, such as an XML document, where tags contain other tags that contain more tags. GroovyMarkup works incredibly well for making Swing applications, which are composed of hierarchies of components such as windows and buttons. The GroovyMarkup tool for Swing is called SwingBuilder.



To use SwingBuilder, you'll need to be familiar with the Swing components (not how to use them, but what they're called and what they're for). A simple overview, with helpful pictures of each component, is available at <http://java.sun.com/docs/books/tutorial/uiswing/components/components.html>.



SwingBuilder has a built-in method for each type of Swing component. When you call one of these methods, the corresponding Swing component is created. Your first method call creates the container (like the main window), and other components are created in the block that follows. Here's a simple SwingBuilder example to get started:




import groovy.swing.SwingBuilder;

swing = new SwingBuilder();
gui = swing.frame(title:'Test Window', size:[200,100]) {
label(text:"This is a test");
}

gui.show();


That's all you need to make a basic window (that code is a complete script -- no additional imports or calls are necessary!). Here's what the result looks like:



image



The way to use SwingBuilder is to first create a root element -- probably a frame (as in the example above), a window, or an applet. After each element call, you can open a block with a curly brace, and add any nested elements you want. (Inside the block, you can call the methods "bare" -- that is, without calling them on the swing object, but just by themselves.) You can also use any other Groovy code -- loops, if statements, other objects -- mixed in with your SwingBuilder calls.



There's a simple trick to making the Swing component method names -- take the Java name for any Swing component, such as "JLabel", remove the "J" and lowercase the first letter (leaving you with "label" in this case). Any Swing component can be made with SwingBuilder using this naming pattern -- the "J-less" name is a method name available for you to use.



With the arguments to each component method call, you can set any properties for that component, which allow you to affect the component's appearance and behavior. We do this with the title and size in the frame call, and the text of the label call, above. (If you are familiar with JavaBeans, these are Bean properties. If you are not familiar with JavaBeans, just look at the documentation for the Swing component you're using, and look for methods starting with get and set -- those are properties. In Java, you would call the setText() method, but with SwingBuilder, you just set the text property as an argument.) Add as many property settings to each component as you want.



Here's a slightly longer example:




import groovy.swing.SwingBuilder;
import java.awt.FlowLayout;

swing = new SwingBuilder();
gui = swing.frame(title:'Test 2', size:[400,200]) {
panel(layout:new FlowLayout()) {
panel(layout:new FlowLayout()) {
for (name in ["Tom", "Dick", "Harry", "Bill"]) {
checkBox(text:name);
}
}

panel(layout:new FlowLayout()) {
comboBox(items:["Red", "Green", "Blue", "Orange"],
selectedIndex:2);
}
}
}

gui.show();


And here's the result:



image



One thing to notice in this second example is that you can often set the model for a MVC component by using a Groovy list or map. Here, we set up the list of options for the JComboBox (better known as a pop-up list) by setting the items parameter with a Groovy list as the value. Much easier than the Java way!



A more complex SwingBuilder application is available in my Bloglines API Client article. That application uses a few other SwingBuilder tricks, like action closures and the widget() call, which will be covered in future posts. You'll see that a huge amount of functionality can be enabled with very little effort -- writing that same application in Java might easily have taken 50 times the lines of code.


2 Comments

jonathan.aquino@gmail.com
2004-10-26 18:58:31
What's the proper way to have components reference each other?
What's the proper way to have components reference each other? For example, how would you have the combobox change the selected checkboxes?
precipice
2004-10-26 19:03:59
What's the proper way to have components reference each other?
The way to do this is with action closures, which I haven't covered yet. I'll write it up tonight if I can. You can see an example in BloglinesClient.groovy -- take a look, for instance, at the itemList.valueChanged definition.