Basically, the Swing designers realized that, in order to have a multi-threaded GUI, you need locks everywhere, which typically means you have bugs everywhere.

That’s not to say a Swing application can’t be multi-threaded. Swing merely requires that the GUI be single-threaded. In Swing, all GUI-related code must run on a special thread called the event dispatch thread, which is automatically created by the Swing framework.

As was pointed out in a comment on my last post, this is how all of my example apps should be started. The invokeLater method takes a Runnable argument. In Clojure, this is easy, because all Clojure functions are Runnable. So, for example, the temp-app program should be started like this:

(SwingUtilities/invokeLater temp-app)

As a consequence of running all GUI code on a single thread, any GUI code that blocks can “freeze” the entire application. Event listeners, therefore, must execute quickly and delegate long operations like I/O to other threads.

Java 6 provides the SwingWorker class to manage long-running background tasks. Unfortunately, the implementation of SwingWorker is heavily dependent on protected methods and concrete inheritance, features that are awkward to use in Clojure.

But wait, wasn’t Clojure designed for concurrency? Yes it was, and we can replace SwingWorker with Clojure’s more-powerful tools.

The point of Flipper is to test the “fairness” of Java’s random number generator. It uses java.util.Random to generate random booleans, simulating a series of coin flips. The number of “heads” (boolean true) should converge to half of the total number of flips.

The Java version of Flipper (source here) does the coin flips in a SwingWorker thread, which sends intermediate results to a GUI.

Our version will use Clojure Agents, a much more flexible and powerful alternative.

Lets dig into some code. First, we need a function to create a “Flipper” agent:

This sets up the initial state of the agent, with its own random number generator, two counters, and a boolean flag to designate whether or not the flipper is running.

The flipper agent will have three actions. An agent action is just a function taking one argument, which is the current state of the agent. Whatever the function returns becomes the new state of the agent.

Additionally, in the body of the action, the special Var *agent* is bound to the agent itself. The action function can send other actions to *agent*; those actions will not run until after the current action completes.

These actions just change the value of :running in the agent’s state. The start action also sends the calculate action to kickstart the calculation loop.

To watch the agent in action, try this at the REPL:

(def flipper (new-flipper))
(send flipper start)

The flipper is now running in the background. At any time, you can retrieve the current state of the flipper with (deref flipper), or simply @flipper. Try it a few times and see how the counters change, as in this sample REPL session:

The if expression is just there to avoid divide-by-zero errors in the initial case.

Note that, although I used the same argument name, state, as in the actions, the error function is not meant to be called as an action with send. Instead, we will call it on the current state of the agent like this:

(error @flipper)

* * *

The nice thing about this flipper is that, unlike the Java version, it is completely decoupled from the GUI. We can design and test it at the REPL before writing any GUI code at all.

(The Java version could have been decoupled. But because Swing requires you to create so many classes anyway, the temptation is always there to combine GUI code with “process” code.)

So let’s get this GUI going. Unlike the Java example, which used callbacks from the flipper to update the GUI, our GUI will update at a fixed rate of 10 times per second. To do this we will use a javax.swing.Timer, which fires an event every n milliseconds.

First, some imports and a helper function to create the text fields with common attributes:

The GUI has three text fields showing the total number of flips, the number of “heads,” and the error rate. The “Start” button starts the flipper; the “Stop” button suspends it. You can start and stop as many times as you like without losing the results of the calculation (another improvement over the Java version, which restarts at zero each time).

The important code is in the with-action bodies. (Don’t confuse Swing ActionListeners with Agent actions.) Remember, event listeners must execute quickly, so all they do is update the visible parts of the GUI.

The “Start” button kicks off the flipper and activates the Timer. The Timer fires every 100 milliseconds, updating the text fields from the current state of the flipper. The “Stop” button suspends both the Timer and the flipper.

Run the application like this:

(SwingUtilities/invokeLater flipper-app)

We didn’t do any fancy layout because it wasn’t necessary for the example. But if you want something prettier, here’s another version using the GridBagLayout macros from my last post:

Most Swing examples don’t translate well into Clojure because they are so thoroughly embedded in the object-oriented paradigm.

A typical Swing example has a main class that extends a container class and implements some *Listener interface. Clojure beginners who try to port these examples may think they need to mimic that same structure.

In fact, there are few situations where Swing forces you to create a subclass. Most involve event listeners and can be handled adequately with Clojure’s proxy.

In this post, we’ll develop a complete, albeit small, Swing application: the classic Temperature Converter tutorial. But ours will be better. It can convert both Celsius to Fahrenheit and vice-versa, and it does the conversion immediately without waiting for a button click.

Before we get to any GUI stuff, we need two functions to convert between degrees Celsius and degrees Fahrenheit:

(defn f-to-c [f]
(* (- f 32) 5/9))
(defn c-to-f [c]
(+ (* c 9/5) 32))

Note the use of Clojure Ratios.

Next, we need a couple of helper functions. First, the parse function will take a String typed by the user and convert it to a number. If the user types an invalid number, parse returns nil, but it can handle extra spaces:

Our temperature converter will have two text fields, one for Celsius and one for Fahrenheit, like this:

As soon as the user types in either text field, the other text field will immediately change to show the converted value. So to convert Celsius to Fahrenheit, just type into the “Celsius” box. To go the other way, type into the “Fahrenheit” box.

I chose this design because it has two elements that behave very similarly, allowing me to show off some higher-order functions.

Let’s start with updating. We have two text fields. We want to update one, call it the “target” field, by converting the value of the other, call it the “source” field. But we never want to update a field while the user is typing in it! That would then trigger another update, causing an infinite loop.

The source and target arguments are JTextFields, which we will create later. The update-temp function will be called every time one of the text fields emits a change event, so first we have to make sure that the source field (the one that triggered the event) has the keyboard focus. If it does, we try to read the source field’s contents. If parse is successful, we can calculate the value for the target field using the supplied convert function, otherwise we just set the target to be blank.

To make this work, we need to attach listeners to each of the JTextFields. We can write a function for that too:

Swing implements a Model-View-Controller paradigm for text fields. So to listen for changes in a text field, we actually want to listen to the Document model associated with that text field. The DocumentListener insertUpdate and removeUpdate methods are called whenever the Document changes. The changedUpdate method is not interesting to us, but we still have to provide an empty implementation in the proxy.

So now we’ve got general-purpose functions for updating one text field whenever another changes. Suppose we create two text fields named celsius and fahrenheit. Wiring them together only takes 2 lines:

GUI layout is hard. You’d be crazy to do it without a GUI designer like Netbeans.

Well, I’m pretty crazy. So I’m going to do some GUI layout in Clojure. And I’m going to use the most intimidating of Java’s GUI layout classes, the GridBagLayout.

Conceptually, GridBagLayout is pretty straightforward. It places components on a flexible grid, in which each column and row is automatically sized to fit the largest component. A set of constraints placed on each component determines its exact placement, size, and alignment.

The devil, as usual, is in the details. GridBagConstraints has 11 fields and 32 constants to control the layout of each component. I won’t try to explain how it works; read the tutorial a few times instead.

The problem with GridBagConstraints, from a Clojure point of view, is that it’s a mutable object with public instance fields. This isn’t a problem for concurrency, because the object is used in only one place, but the syntax is awkward:

This macro takes a field name as a keyword and sets the value of that field. I used keywords instead of bare symbols because they tend to signal names or constants in Clojure code.

The macro has one other trick up its sleeve: if the value of a field is a keyword, it gets used as the name of a static field (constant) in GridBagConstraints.

With this macro, the set!s in the previous example become:

(set-grid! c :gridx 1)
(set-grid! c :gridy :RELATIVE)

So far, so good. But we’ve only replaced a bunch of set!s with a bunch of set-grid!s.

What we really want is a terse syntax for specifying constraints. There are many ways to do this. I could write a macro that creates a new GridBagConstraints for each component. But that would require a lot of repetition.

Often one wants to reuse the same constraint for several components in a row. The tutorial examples achieve this by using a single instance of GridBagConstraints and modifying its fields for each component. (The definition of GridBagLayout explicitly permits this.)

So what I want is a macro that allows me to add components to a container, in any order, specifying only the constraints that need to change for each component. Here’s what it will look like:

The first argument to the macro is a container with a GridBagLayout as its layout manager. What follows is a mixture of components and constraints. Each component is added to the layout with the current set of constraints. A keyword signals a change to a constraint field, and is immediately followed by its value. Once a field is set, it retains its value until it is set again.

The line breaks and commas are just whitespace; what matters is the order.

You’ll have to take my word for it that this macro was not especially difficult to write. As for what it does, it loops through the body and recursively constructs code for the result. When it encounters a keyword, it uses the set-grid! macro I defined earlier. Otherwise, it assumes the expression is a component, and adds it to the container. (The manual gensyms are necessary because of the nested backquotes.)

Here’s an example that creates a layout with three buttons, as in this screenshot:

Admittedly, this is not all that much shorter than the equivalent Java code. But it’s still shorter, without diminishing the power or flexibility of the original API.

This is the kind of mini-language for which Lisp is famous. And it’s only the beginning. We could go on to define a more complete, expressive, and functional language for designing GUIs. But that will have to wait for another post.

You can run counter-app at the REPL and see the resulting GUI layout, although the button doesn’t do anything yet.

The annoying thing about this code is the imperative style Swing forces on us: construct local variables and hammer at them with method calls.

Fortunately, Clojure has a handy built-in macro for just this kind of situation: doto. The doto macro takes a body of expressions. It evaluates the first expression and saves it in a temporary variable, and then inserts that variable as the first argument in each of the following expressions. Finally, doto returns the value of the temporary variable. An example will make more sense:

The on-action macro’s first argument is any component (such as JButton) that has an addActionListener method. The body of the macro is the code that will be executed when the ActionListener is triggered. The event argument is just a symbol; it will be bound to the ActionEvent that triggered the listener. (We could have used a fixed symbol like “this”, but that would be bad macro design.)

JFrame is Swing’s all-purpose window class. This example created a frame, set its dimensions to 200×200 pixels, and “turned it on” by calling setVisible.

Containers and Frames

Our new frame doesn’t look like much; let’s give it some content. More specifically, let’s give it a container. Swing GUIs are laid out as a nested hierarchy of containers. All containers — except the top-level window — are sub-classes of JComponent. This is called the containment hierarchy.

Although it’s technically possible to add GUI elements directly to a top-level container like JFrame, it’s more correct to use a content pane. We’ll use JPanel, a general-purpose container:

Hey, it’s not there! That’s because Swing wasn’t designed with interactive development in mind. To make your button visible, call:

(.revalidate button)

The revalidate method is not something you’ll read about in most Swing tutorials, because in pre-compiled Java it’s rarely necessary. Basically, it tells Swing, “I just changed the layout, you need to redraw stuff.” Starting at our JButton, Swing searches up the containment hierarchy to the top-level container, and redraws it.

Next step: Action! My next post will talk about enabling GUI events with ActionListener.