03 February 2009

Creating a Clojure GUI Application with SWT

In my explorations of Clojure, I have been developing a desktop GUI application that uses SWT, the graphics toolkit that Eclipse uses. Once you get going, SWT is fairly intuitive to program in with Clojure, but you might need a little help to get started. Here is an example of a barebones app in SWT:
(ns swttest
(:import (org.eclipse.swt.widgets Display Shell)
(org.eclipse.swt.layout GridLayout)
(org.eclipse.swt.events ShellAdapter)))

(defn create-shell [display shell]
(let [layout (GridLayout.)]
(doto shell
(.setText "SWT Test")
(.setLayout layout)
(.addShellListener
(proxy [ShellAdapter] []
(shellClosed [evt]
(System/exit 0)))))))

(defn swt-loop [display shell]
(loop []
(if (.isDisposed shell)
(.dispose display)
(do
(if (not (.readAndDispatch display))
(.sleep display))
(recur)))))

(defn begin []
(let [display (Display.)
shell (Shell. display)]
(create-shell display shell)
(.setSize shell 700 700)
(.open shell)
(swt-loop display shell)))

(begin)
On Mac, you will need to add the "-XstartOnFirstThread" command line option or your application will crash soon after launching.

Update:
I originally left out the line "(create-shell display shell)". The code above is now corrected.

See also:

6 comments:

Anonymous said...

I cant get this to work:

java -XstartOnFirstThread -cp .:swt-3.4-carbon-macosx/swt.jar -jar /opt/local/bin/clojure/clojure.jar swttest.clj

it says java.lang.ClassNotFoundException: org.eclipse.swt.widgets.Display (swttest.clj:0)

Jānis Džeriņš said...

Where exactly is the create-shell function supposed to be used?

Jānis Džeriņš said...

Where exactly is create-shell function supposed to be used?

Vincent Foley said...

Don't you need to call create-shell at one point?

Unknown said...

Janis and Vincent:

Thanks for catching my mistake. The code as it is above should work as intended now.

--Kevin

Unknown said...

Mr. "Default",

Try this:
java -XstartOnFirstThread -cp .:path/to/clojure.jar:path/to/swt.jar clojure.lang.Script swttest.clj

--Kevin