Swing Into Actions with Clojure

My previous post left you with a Clojure/Swing GUI consisting of one window and one button.  Boring!  Let’s make it do something.

To catch up, start a Clojure REPL and type:

(import '(javax.swing JFrame JPanel JButton))
(def button (JButton. "Click Me!"))
(def panel (doto (JPanel.)
             (.add button)))
(def frame (doto (JFrame. "Hello Frame")
             (.setSize 200 200)
             (.setContentPane panel)
             (.setVisible true)))

Boom, one window-and-button on the screen.

Let’s make our button do something.  First, we’ll define a function for what we want to do:

(import 'javax.swing.JOptionPane)
(defn say-hello []
  (JOptionPane/showMessageDialog
    nil "Hello, World!" "Greeting"
    JOptionPane/INFORMATION_MESSAGE))

You can call the say-hello function directly; it pops up a dialog box, using the utilities in JOptionPane.

To connect this function to our button, we have to provide a class implementing the ActionListener interface.  Clojure’s proxy feature is the easiest way to do this:

(import 'java.awt.event.ActionListener)
(def act (proxy [ActionListener] []
           (actionPerformed [event] (say-hello))))

Now act is an instance of an anonymous class implementing the actionPerformed method.  We can attach this class as a listener of our button:

(.addActionListener button act)

And we’re done!  Click the button, and a dialog box pops up.

4 Replies to “Swing Into Actions with Clojure”

  1. (import ‘(javax.swing JFrame JFrame JButton)) should be (import ‘(javax.swing JFrame JPanel JButton)).
    Also (def act (proxy [ActionListener] []…. requires (import ‘(java.awt.event ActionListener))

  2. Maybe I’m doing something wrong, but I found that say-hello didn’t exist after declaration, being named ‘user/say-hello’. This was usable at both stages (immediate invocation in REPL and invocation within the proxy).

    Just a heads-up for the newbies like me who are following along.

  3. Hi Chris,
    Not sure what might have caused that, unless you’re using an IDE that sets the default namespace to something other than ‘user’.

Comments are closed.