Václav is a programming enthusiast who's constantly seeking ways to make development more effective and enjoyable. He's particularly interested in server-side Java technologies, distributed systems, concurrency, agile methodologies, modern programming languages and DSLs.
He works for JetBrains as a senior software developer and a technology evangelist. He is also a board member of the JetBrains Academy. On the side, he's leading the GPars project, an opensource concurrency library, and investigates the domains of neural networks, evolutionary programming and data mining. You can check out his blog or follow him on twitter.
[dzone] Václav is a DZone Zone Leader and has posted 45 posts at DZone. View Full User Profile

Swinging in Groovy is fun

02.08.2008
| 9334 views |
  • submit to reddit

There are several ways to create UI in Swing. Some people prefer writing the code by hand, some use graphical Swing designers instead. Groovy adds another possibility - the SwingBuilder. Leveraging the power of Groovy builders the SwingBuilder allows you to create UI by hand yet very efficiently.

To be concrete, here is a very simple Swing app written in Groovy, which automatically updates a label with whatever is in the text field. The example uses binding between Swing components.

JFrame frame = new SwingBuilder().frame(title: 'Binding sample',
defaultCloseOperation: JFrame.EXIT_ON_CLOSE) {
vbox {
JTextField valueToCalculate = textField()
label(text: bind(source: valueToCalculate,
sourceProperty: 'text',
converter: {it.toUpperCase()}))
}
}

I needed only 6 lines of self-explanatory code. What makes me more confident that this is a reasonable way to write Swing code is that the full power od Java-written Swing code is still at my fingertips. I can revert to plain Swing API any time for any parts of my code, like in the next demo, where I mix binding with classical Java or Groovy written KeyListener.

JFrame frame = new SwingBuilder().frame(title: 'Binding sample',
defaultCloseOperation: JFrame.EXIT_ON_CLOSE) {
vbox {
JTextField valueToCalculate = textField()
label(text: bind(source: valueToCalculate,
sourceProperty: 'text',
converter: {it.toUpperCase()}))
valueToCalculate.addKeyListener(new MyKeyListener())
}
}

Swing multithreading in Groovy

The SwingBuilder is also very effective when dealing with concurrency in Swing applications. Let say we need to perform a time-demanding db operation. May be, to retrieve some value from a db based on the value in a text field and show the result by updating the text of a label. We certainly have to invoke a separate thread to avoid freezing our UI and use SwingUtilities.invokeLater() to update the label with the result once we get it from the db. In Java we would need to create a new thread to run the retrieval and define a Runnable to update the UI. In Groovy we need only three lines of code to define the button and the operation, including all the multithreading boilerplate code. We leverage the doOutside() and doLater() methods, which create a new thread for communication with the db and update UI with the result inside the event queue thread respectively.

JFrame frame = new SwingBuilder().frame(title: 'Threading sample',
defaultCloseOperation: JFrame.EXIT_ON_CLOSE) {
vbox {
JTextField entityId = textField()
JLabel entityName = label(text: '')
button('Retrieve value from DB', actionPerformed:{doOutside{
def result = retrieveEntity(entityId.text)
doLater{entityName.text = result}
}})
}
}

The doLater() call assigns a UI update task to the event queue asynchronously. For synchronous call we can use edt() instead.

I guess that's pretty neat, isn't it? In my opinion, the SwingBuilder together with the GraphicsBuilder are very powerful tools, or DSLs if you like, for UI development on the Java platform.


This post originated at my blog - Swing binding and Swing multithreading in Groovy.
5
Your rating: None Average: 5 (1 vote)
Published at DZone with permission of its author, Václav Pech.

Comments

replied on Sun, 2008/04/27 - 9:01am

Hi, can I also use the doOutside with widgets ?

Václav Pech replied on Thu, 2008/06/12 - 1:40pm

The code inside doOutside() will be invoked in a separate thread, so you can put any code there that you would normally run in a separate thread. Just make sure that all the code that must be run in the Swing event queue, like manipulation of Swing components, should be wrapped with either edt() or doLater() to prevent race conditions.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.