Monday, 3 October 2011

Hello to GUI

The next example shows the minimum possible graphical user interface application. It consists just of a window with the words “Hello World” written in it. This is based on the first example in the Java Swing Tutorial. Here is the Clojure code:

(ns clojurecorner
  (:import (javax.swing JFrame JLabel SwingUtilities)))

(defn create-and-show-gui []
  (. SwingUtilities invokeLater
    (proxy [Runnable] []
      (run []
        (JFrame/setDefaultLookAndFeelDecorated true)
        (let [frame (JFrame. "Hello World from Swing")
              label (JLabel. "Hello World")]
          (.setDefaultCloseOperation frame JFrame/EXIT_ON_CLOSE)
          (.add (.getContentPane frame) label)
          (.pack frame)
          (.setVisible frame true))))))


There are various new things happening here. Well, new to me.  First, we have imported some items from the Swing library: JFrame is the object that produces the window on the desktop, and JLabel will support the label that we will put in the frame. SwingUtilities provides essential code to run the application.

The example consists mostly of the call to the function create-and-show-gui. Now, to make this work properly we want this code to be executed in the event dispatch thread, not in our forground thread. We achieve this by passing the code to the function invokeLater in the Swing object SwingUtilities. This function requires an object that implements the interface Runnable, which essentially means it has to provide a function run(). To pass our code to the Java routines we bundle it up into a proxy: the Clojure function proxy takes, first, the class or interface to be represented (here it's Runnable), then any parameters required by a superclass (none here), and then the function or functions to be implemented – in this case the function run.

So the code in run is executed via the call to SwingUtilities.invokeLater() - this means that our main code calls this and then proceeds, allowing Swing to run the code to create the window in its own time in its own thread.

Within the function run we start by switching on the default look and feel for the GUI – that is to say the default Swing appearance. Without this the interface will get your native GUI appearance. It will still work like that, of course, it's just a matter of how you want it to look.

Next we create a frame object from the class JFrame and a label object from the class JLabel.

The next line sets the close operation to halt the program – this means that when you click the close box in the frame the application will actually close as you would expect, not just sit there.

The call to function .add inserts the label into the content area of the label, so the text will appear in the window.

The call to .pack makes the components shuffle into position and then the call to setVisible allows the window to appear on the screen.

When it appears it is in its tiniest area, but you can drag it around and open it up to read what the label says.  So it does the minimum that a GUI window needs to do.  You have to start somewhere.

No comments:

Post a Comment