GUIs in Clojure

735 views
Skip to first unread message

Mitch

unread,
Oct 8, 2008, 4:07:23 PM10/8/08
to Clojure
I'm interested in doing a GUI program in clojure, but the functional
style of clojure doesn't seem to blend too well with the normal Java
GUI libraries. Does anybody have any advice on using clojure for GUI
programming? I've seen Rich's ants demo, but that isn't really an
event driven GUI program (just a nice display for his simulation).
Has anyone tried using of the GUI building tools for Java with
clojure? I feel like these could help a lot, but I'm not sure.

Thanks,
Mitch

Bob

unread,
Oct 8, 2008, 5:37:01 PM10/8/08
to Clojure
Yes, I'm very interested in this question as well. I'm learning
clojure and its my first attempt at functional programming. And I was
thinking of writing a swing GUI program to try it out. But it would
seem the GUI state is going to be a mass of mutable state which
doesn't map well to the functional style. What am I missing? Does
anyone have a non-trivial example of a Swing program done the Clojure
way?

Thanks much,
Bob

Ande Turner

unread,
Oct 8, 2008, 6:06:12 PM10/8/08
to clo...@googlegroups.com
As I've just picked up on Clojure myself. First of all I was wondering if anyone was using the Qt's Jambi bindings for GUIs  ?

I'm just delving into the details of how Swing is implemented at the moment, can't say I agree with half of the "design" decisions myself.  Swing isn't thread safe, although AWT is to my knowledge, and that feels wrong considering the how great Clojure handles concurrency. Perhaps a Clojure library bound to AWT directly would be a worthwhile side-project, thus eliminating Swing completely. It would be nice to get rid of the weakest link.

:)
Ande


2008/10/9 Bob <bobnn...@gmail.com>

Chouser

unread,
Oct 8, 2008, 6:10:02 PM10/8/08
to clo...@googlegroups.com
On Wed, Oct 8, 2008 at 5:37 PM, Bob <bobnn...@gmail.com> wrote:
> Does anyone have a non-trivial example of a Swing program done the
> Clojure way?

This probably only counts as trivial, but it's what I've got, so I
hope it helps a little. I wrote it up for a talk I gave, so it can be
run a demo, dropping each top-level form into a REPL one at a time,
watching the GUI change as you go. I hope it helps a little...

I start my REPL like this:
rlwrap java -server -cp
~/build/clojure/clojure.jar:/usr/share/java/postgresql-jdbc3-8.2.jar
-Djdbc.drivers=org.postgresql.Driver clojure.lang.Repl

Then I paste into it each of these forms:

(import '(javax.swing JFrame JPanel JScrollPane JTable SwingUtilities)
'(javax.swing.table AbstractTableModel DefaultTableCellRenderer)
'(java.awt Dimension GridLayout Font Color)
'(java.awt.event MouseAdapter)
'(java.sql DriverManager))

(def table (JTable.))

(. SwingUtilities invokeLater
(fn []
(doto (JFrame. "demo")
(setDefaultCloseOperation (. JFrame EXIT_ON_CLOSE))
(setContentPane
(doto (JPanel. (GridLayout. 1 0))
(setOpaque true)
(add (JScrollPane.
(doto table
(setPreferredScrollableViewportSize
(Dimension. 500 70))
(setFillsViewportHeight true))))))
(pack)
(setVisible true))))

; at this point you should have a window

; modify this line based on your database server, db name, password, etc:
(def conn
(. DriverManager getConnection "jdbc:postgresql:mydb" "postgres" "system"))

(defn query-vec [sql]
(with-open stmt (.createStatement conn)
(vec (resultset-seq (.executeQuery stmt sql)))))

; modify this line based on your table name:
(def rows (query-vec "SELECT * FROM LogB"))

(defn model [rows col-names value-at]
(proxy [AbstractTableModel] []
(getRowCount [] (count rows))
(getColumnCount [] (count col-names))
(getColumnName [c] (nth col-names c))
(getValueAt [r c] (value-at r c))
(isCellEditable [r c] false)))

(.setModel table (model rows
["foo" "bar" "baz"]
(fn [r c] (str r ", " c))))

; at this point you should have a fairly meaningless grid

(.setModel table (model rows
["record"]
(fn [r c] (prn-str (nth rows r)))))

(.setModel table (model rows
(vec (map str (keys (first rows))))
(fn [r c] ((nth rows r) (nth (keys (first rows)) c)))))

; modify this based on the actual columns in your table:
(.setModel table (model rows
["Time" "Source" "Message"]
(fn [r c] (let [row (nth rows r)]
((nth [#(:createtime row)
#(str (:path row) ":" (:line row))
#(:buffer row)] c))))))

(.setDefaultRenderer table Object
(proxy [DefaultTableCellRenderer] []
(getTableCellRendererComponent [tbl obj isSelected hasFocus r c]
(let [{:keys [level]} (nth rows r)]
(doto this
(setForeground (cond (<= level 0) (. Color white)
(<= level 10) (. Color blue)
(<= level 20) (. Color red)
(<= level 30) (. Color magenta)
:else (. Color black)))
(setText (str obj)))))))

(.addMouseListener table
(proxy [MouseAdapter] []
(mouseClicked [e]
(when (== (.getClickCount e) 1)
(let [p (.getPoint e)
r (.rowAtPoint table p)
c (.columnAtPoint table p)]
(prn "click row " r)
(flush))))))

--Chouser

Michael Beauregard

unread,
Oct 8, 2008, 6:19:42 PM10/8/08
to clo...@googlegroups.com
I spent a few hours writing a macro that would allow a more
declarative gui than the usual swing approach. I didn't finish it, but
concluded that this could be quite doable. For example, I was aiming
for a macro that would allow the following declarative style:

[Note that I don't have the actual code or example that I had working
since that is on my laptop hibernating at home atm.]

; rough example
(make-ui
'(JFrame {:title "The title"}
(JLabel {:id fooLabel :text "Some label"})
(JButton {:id btn1 :label "Click me" :actionPerformed (fn [evt]
(println "clicked")) })
(JButton {:label "Apply" :actionPerformed someFn :enabled false })))

This doesn't address the functional/stateless impedance mismatch, but
would make defining guis simpler. However, the basic idea is to
represent the containment hierarchy inherent in a gui with the nesting
of lisp expressions. The map of attributes would be applied as setters
on each component after it is created. The event handlers such as
":actionPerformed" are harder, but also doable.

The nasty part that I haven't spent any time thinking about is the
LayoutManager gong show in swing. That sounds much harder to solve
declaratively without writing a bunch of LMs that support simplifying
the declarative style.

Michael

Tom Emerson

unread,
Oct 8, 2008, 7:16:28 PM10/8/08
to clo...@googlegroups.com
Putting on a heretical hat, it seems that trying to utilize a GUI
library designed for Java's imperative programming model from a
functional language is an exercise in frustration trying to pound a
square peg through a round whole. While I like Chouser's example (it's
very cool, and makes a good demo) I'm not sure how realistic this is
for a non-trivial GUI app. How do people see the thread model used by
Swing working with Clojure's?

--
Tom Emerson
trem...@gmail.com
http://www.dreamersrealm.net/~tree

Ande Turner

unread,
Oct 8, 2008, 7:55:52 PM10/8/08
to Clojure
Personally I've always had a through dislike for Swing, and now I'm
looking into its implementation I dislike it even more. Replacing
Swing entirely would be something I could seriously delve into!

I like the idea of using a XAML style layout-file to create UIs. A
threadsafe Swing replacement which would parse these at runtime, or
something that would complie a layout-file into bytecode are two
options off the top of my head. Would most of you like standard
library of windows and dialogs in Clojure? < A list of suggested
essentials windows and dialogs would be appreciated.

Are there any examples of GUI libraries designed for the functional
programming model that you know of I could go examine first? Purely
from a syntax point of view. Lispers? Is there such as thing
already?

- Ande
> > On Wed, Oct 8, 2008 at 3:37 PM, Bob <bobnnamt...@gmail.com> wrote:
>
> >> Yes, I'm very interested in this question as well.  I'm learning
> >> clojure and its my first attempt at functional programming.  And I was
> >> thinking of writing a swing GUI program to try it out.  But it would
> >> seem the GUI state is going to be a mass of mutable state which
> >> doesn't map well to the functional style.  What am I missing?  Does
> >> anyone have a non-trivial example of a Swing program done the Clojure
> >> way?
>
> >> Thanks much,
> >> Bob
>
> >> On Oct 8, 2:07 pm, Mitch <mitchell.kot...@gmail.com> wrote:
> >>> I'm interested in doing a GUI program in clojure, but the functional
> >>> style of clojure doesn't seem to blend too well with the normal Java
> >>> GUI libraries.  Does anybody have any advice on using clojure for GUI
> >>> programming?  I've seen Rich's ants demo, but that isn't really an
> >>> event driven GUI program (just a nice display for his simulation).
> >>> Has anyone tried using of the GUI building tools for Java with
> >>> clojure?  I feel like these could help a lot, but I'm not sure.
>
> >>> Thanks,
> >>> Mitch
>
> --
> Tom Emerson
> tremer...@gmail.comhttp://www.dreamersrealm.net/~tree

Stuart Sierra

unread,
Oct 8, 2008, 8:47:51 PM10/8/08
to Clojure
On Oct 8, 7:55 pm, Ande Turner <ande.tur...@gmail.com> wrote:
> Are there any examples of GUI libraries designed for the functional
> programming model that you know of I could go examine first?  Purely
> from a syntax point of view.  Lispers?  Is there such as thing
> already?

There are a handful of Common Lisp GUIs, most of them rather dated:
Garnet: http://garnetlisp.sourceforge.net/
McCLIM: http://common-lisp.net/project/mcclim/

Most of the others are bindings to C/C++ libraries:
FLTK: http://common-lisp.net/project/cl-fltk/
Cells-GTK: http://common-lisp.net/project/cells-gtk/
LTK: http://www.peter-herth.de/ltk/

-Stuart

Stephen C. Gilardi

unread,
Oct 8, 2008, 9:11:56 PM10/8/08
to clo...@googlegroups.com

On Oct 8, 2008, at 6:19 PM, Michael Beauregard wrote:

The nasty part that I haven't spent any time thinking about is the
LayoutManager gong show in swing. That sounds much harder to solve
declaratively without writing a bunch of LMs that support simplifying
the declarative style.

Possibly of interest for the layout part of that, I recently checked in clojure.contrib.miglayout which provides support for using MiGLayout (http://miglayout.com) from Clojure. It removes some of the repetitive code from the task of populating a JPanel and providing constraints for miglayout.

The constraints are ultimately passed as strings, but in the clojure code they can be strings, keywords, vectors, or keywords for convenience:

-------------------------
clojure.contrib.miglayout/miglayout
([container & args])
  Adds java.awt.Components to a java.awt.Container with constraints
  formatted for the MiGLayout layout manager.

  Arguments: container layout-constraints? [component constraint*]*

    - container: the container for the specified components, its layout
      manager will be set to a new instance of MigLayout
    - layout-constraints: an optional map that maps any or all of
      :layout, :column, and/or :row to a string that specifies the
      corresponding constraints for the whole layout
    - an inline series of components and constraints: each component may be
      followed by zero or more component constraints

  The set of constraints for each component is presented to MiGLayout as a
  single string with each constraint and its arguments separated from any
  subsequent constraint by a comma.

  Component constraint: string, keyword, vector, or map

    - A string specifies one or more constraints each with zero or more
      arguments. If it specifies more than one constraint, the string must
      include commas to separate them.
    - A keyword specifies a single constraint without arguments
    - A vector specifies a single constraint with one or more arguments
    - A map specifiess one or more constraints as keys, each mapped to a
      single argument

  Empty strings, vectors, and maps are accepted but don't affect the
  layout.

Here's an example from clojure.contrib.miglayout.test (based on a Java example at http://www.devx.com/java/Article/38017/1954 )

(the constraints line up in a monospaced font)

  (fn test2
    [panel]
    (miglayout panel
      {:column "[right]"}
      (JLabel. "General")   "split, span"
      (JSeparator.)         :growx :wrap
      (JLabel. "Company")   [:gap 10]
      (JTextField. "")      :span :growx
      (JLabel. "Contact")   [:gap 10]
      (JTextField. "")      :span :growx :wrap
      (JLabel. "Propeller") :split :span [:gaptop 10]
      (JSeparator.)         :growx :wrap [:gaptop 10]
      (JLabel. "PTI/kW")    {:gapx 10 :gapy 15}
      (JTextField. 10)
      (JLabel. "Power/kW")  [:gap 10]
      (JTextField. 10)      :wrap
      (JLabel. "R/mm")      [:gap 10]
      (JTextField. 10)
      (JLabel. "D/mm")      [:gap 10]
      (JTextField. 10)))

--Steve

Parth Malwankar

unread,
Oct 9, 2008, 12:31:14 PM10/9/08
to Clojure


On Oct 9, 6:11 am, "Stephen C. Gilardi" <squee...@mac.com> wrote:
> On Oct 8, 2008, at 6:19 PM, Michael Beauregard wrote:
>
> Possibly of interest for the layout part of that, I recently checked  
> in clojure.contrib.miglayout which provides support for using  
> MiGLayout (http://miglayout.com) from Clojure. It removes some of the  
> repetitive code from the task of populating a JPanel and providing  
> constraints for miglayout.
>

Thanks for this Steve. This is definitely useful. I look forward
to using this functionality more.

Parth

falcon

unread,
Oct 9, 2008, 4:26:58 PM10/9/08
to Clojure
I think it will be far better to model any Clojure GUI libraries on
JavaFX rather than straight Swing. In fact, some code samples people
have posted here remind me of JavaFX code.

Don Sym, of F# develops his programs on the command line,
instantiating GUIs along the way to peek inside data structures or to
keep and eye on how values of variables change. Clojure certainly
should be able to do that, as long as the library is designed with
that in mind.

David Powell

unread,
Oct 10, 2008, 9:25:55 AM10/10/08
to clo...@googlegroups.com

> I'm just delving into the details of how Swing is implemented at
> the moment, can't say I agree with half of the "design" decisions
> myself. Swing isn't thread safe, although AWT is to my knowledge,

Actually, AWT isn't thread-safe either. Documentation about the fact
seems pretty hard to find. From what I can gather, in Java 1.1, AWT
claimed to be thread-safe, but there were problems with races and
deadlocks, therefore in Java 1.2 and above AWT doesn't claim to be
thread-safe. AWT does seem to mostly work if you call it from multiple
threads.

Some discussion here:

http://www.elharo.com/blog/software-development/java/2006/11/10/awt-on-the-event-dispatch-thread/

A brief official reference here:

http://java.sun.com/j2se/1.5.0/docs/guide/deployment/deployment-guide/applet-compatibility.html

Also here:

http://web.archive.org/web/20060816013814/http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html

There's some more info here about why multi-threaded GUI toolkits
aren't such a good idea:

http://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html

Restricting GUI objects to only work from one thread is done so that
they don't need to use locking, which makes them faster and less prone
to bugs. Lots of GUI toolkits do this, eg: Win32, .NET, SWT. Allowing
objects to be accessed from multiple threads makes things slightly
easier for clients, but isn't really going to improve performance.

Swing does have some annoying aspects of its design (its fake platform
UI isn't all that convincing), but I don't think that the
single-threaded access model is that bad a thing.

--
Dave


Ande Turner

unread,
Oct 10, 2008, 4:42:28 PM10/10/08
to clo...@googlegroups.com
David,

Thank you very much for such an expansive response.  Currently a thread-safe Swing alternative is using the Jambi bindings for Qt. I neglected to provide a link to details before so here it is:
Although this solution does add a layer of uncertainty, and may not warrant the installation hassles.  Personally, I rarely do GUI work, but I intend to do alot very soon.  Since my last post I communicated with a guy at Sun specifically about AWT, and now, for purely academic purposes, I will be writing an AWT & Swing replacement utilising XToolkit bound to a modified Xlib with Solaris being the target system.  (phew, try and say that ten times fast)  Perhaps its needless to say, but the project it will have a rather esoteric approach.  Anyways, I hope to have the design finished by New Years.  Thanks again David for your response.

Cheers,
Ande

2008/10/11 David Powell <djpo...@djpowell.net>

Colin Walters

unread,
Oct 10, 2008, 5:08:01 PM10/10/08
to Clojure
On Oct 10, 4:42 pm, "Ande Turner" <ande.tur...@gmail.com> wrote:
> David,
> Thank you very much for such an expansive response.  Currently a thread-safe
> Swing alternative is using the Jambi bindings for Qt. I neglected to provide

Hmm? Qt isn't really any more threadsafe than Swing is, or than GTK+
is:

http://doc.trolltech.com/4.0/threads.html :
"Although QObject is reentrant, the GUI classes, notably QWidget and
all its subclasses, are not reentrant. They can only be used from the
main thread."

GUI programs by their very nature have a large amount of state, and
the object-oriented paradigm makes a lot of sense. So back to the
original question - probably what makes the most sense with Clojure is
to write nontrivial GUI components in Java, and the interact with your
GUI code via Clojure's Java integration.

Ande Turner

unread,
Oct 10, 2008, 5:20:36 PM10/10/08
to clo...@googlegroups.com
Apologies Colin...  I'll just say I was a victim of Trolltech marketing, that wasn't the impression I got.

2008/10/11 Colin Walters <cgwa...@gmail.com>

John

unread,
Oct 10, 2008, 7:43:09 PM10/10/08
to Clojure
Allegedly gnome-java is threadsafe, but it only works on Linux,
unfortunately.

http://research.operationaldynamics.com/blogs/andrew/software/java-gnome/

On Oct 10, 5:20 pm, "Ande Turner" <ande.tur...@gmail.com> wrote:
> Apologies Colin...  I'll just say I was a victim of Trolltech marketing,
> that wasn't the impression I got.
>
> 2008/10/11 Colin Walters <cgwalt...@gmail.com>

Stuart Sierra

unread,
Oct 10, 2008, 11:18:23 PM10/10/08
to Clojure
On Oct 8, 6:19 pm, "Michael Beauregard" <mich...@insightfulminds.com>
wrote:
> This doesn't address the functional/stateless impedance mismatch, but
> would make defining guis simpler. However, the basic idea is to
> represent the containment hierarchy inherent in a gui with the nesting
> of lisp expressions.

That's a cool idea. Reminds me of Shoes: http://shoooes.net/
It's a clever little Ruby GUI that uses nested containers and
anonymous callback functions.
-Stuart Sierra

Michael Beauregard

unread,
Oct 11, 2008, 12:00:25 AM10/11/08
to clo...@googlegroups.com
Part of why I didn't really follow through with this yet is that I'm
actually not very interested in swing. After doing a 2 year contract
using it I'm not sure I could use or recommend swing for anything
substantial with a straight face. I find it clumsy and over
complicated. Even still, it seems that it could be fun to use it for
small stuff from Clojure.

I've been using Flex a lot lately and it is a very nice way to do GUI
programming. Not perfect, but better than other things I've used by
quite a margin. I'll be sure to check out Shoes. Thanks for the tip.

Michael

Michael Beauregard

unread,
Oct 11, 2008, 12:08:38 AM10/11/08
to clo...@googlegroups.com
I still don't really see why a multi-threaded UI framework is
important. You can have a multiple threads use Swing's
invokeLater(Runnable r) api to submit UI work. And since Clojure fns
implement Runnable, you can just post fns into Swing to do your UI
updates. I don't think you even *want* a multi-threaded UI framework
considering the threading bugs and performance problems it probably
has (inherent to implementing complex concurrency with old school
locking semantics).

Martin DeMello

unread,
Oct 11, 2008, 12:34:48 AM10/11/08
to Clojure
On Oct 10, 9:08 pm, "Michael Beauregard" <mich...@insightfulminds.com>
wrote:
> I still don't really see why a multi-threaded UI framework is
> important. You can have a multiple threads use Swing's
> invokeLater(Runnable r) api to submit UI work. And since Clojure fns
> implement Runnable, you can just post fns into Swing to do your UI
> updates. I don't think you even *want* a multi-threaded UI framework
> considering the threading bugs and performance problems it probably
> has (inherent to implementing complex concurrency with old school
> locking semantics).

At the extremely simple end of that scale is gtk-server:
http://www.gtk-server.org/index.html

martin

Monsieur Pinocchio

unread,
Oct 12, 2008, 9:53:25 PM10/12/08
to clo...@googlegroups.com
I took a shot at Clojure GUI programming sometime back... my basic aim was to "impedance
match" the functional style with GUI programming... I wanted to develop a substantial Swing app then but have not been getting time to do that.

I found agents and sending messages to agents a nice fit for GUI programming because agents like GUIs hold state and respond serially to a set of messages (for GUIs its re-paint and user events). Swing is single threaded and hence the "serial" parallel truly holds.

However, retrofitting Swing state in a "global-across-vm" clojure agent seemed like too much work and overloading clojure with bloat. So I instead tried hiding things behind syntax using the following macro:

(defmacro swing [exp]
        (list 'if '(. javax.swing.SwingUtilities (isEventDispatchThread))
                exp
                (list '. 'javax.swing.SwingUtilities (list 'invokeAndWait
                                                                (list 'proxy '[Runnable] '[] (list 'run '[] exp))))))

The idea is that the expression
(swing <clojure expression> )
causes the <clojure expression> to be evaluated in the EventThread... kinda like agents but this time ensuring that there is only a single thread in the VM where this gets executed.

Next I developed simple clojure wrappers over Swing components like the following:
(defn label [txt]
        (new javax.swing.JLabel txt))

(defn action [txt func]
        (proxy [javax.swing.AbstractAction] [txt] (actionPerformed [e] (func (.getSource e)))))

(defn button [act]
        (new javax.swing.JButton act))

(defn comboBox [items func]
        (let [ cb (new javax.swing.JComboBox items) ]
;               (.setEditable cb false)
                (.addActionListener cb (proxy [java.awt.event.ActionListener] []
                                                                        (actionPerformed [e]
                                                                               (func (.getSource e)))))
        cb))

... hope you get the idea. Now, these can be used as:

; Construct a dropdown menu for selecting folders
(def folders (comboBox (to-array (list "Inbox" "Sent" "Drafts" "Trash"))
                                           (fn [l] (.. System out (println (.getSelectedItem l))))))
; .... more code here....

; Set the content pane to be a split pane with a label and the mail index
(swing (.setContentPane frame mailContent))

... and so on and so forth.

I do like the idea of using clojure syntax to layout GUIs succinctly. That was kind of my aim when going with simple wrappers over Swing components.

For GUIs, JavaFX seems to have a killer feature that clojure doesn't have (or maybe cannot have because of its take on data-structure mutation)... bindings. JavaFX supports running code blocks upon changes to specific variables/properties inside a GUI object (constructed in JavaFX using a declarative programming style). This "reactive" programming style seems to be a good fit for GUI programming.

It may be possible to do something similar by adding optional "hook" functions with the swing component wrappers which trigger on PropertyChangeEvents from swing components. I have not tried implementing this but I think that hiding these details behind the syntax of a clojure GUI library may be the easiest way to give the programmer an impression of JavaFX style bindings.

--
Pinocchio

JumpingJupiter

unread,
Oct 13, 2008, 3:37:46 PM10/13/08
to Clojure
I wrote some code to enable declarative swing definitions pretty much
identical in form to Michael's suggestion:

(let [gui
(swingset
(JFrame frame {:setSize [500 500]}
(JPanel panel {:setBackground (. Color orange)}
(JLabel {:setText "Hello World. Welcome to my Swing GUI
created from Clojure."})
(JPanel {:setLayout (new BorderLayout)}
(JTextArea { :setText "type here and marvel as nothing
happens!"}))
(JButton btn {:setText "Close"})))
(GridLayout layout {:setColumns 1 :setRows 3})
(JMenuBar menubar
(JMenu {:setText "File"}
(JMenuItem {:setText "Save" :addActionListener (actionListener (fn
[e] (println "Sorry, can't save")))}))
(JMenu {:setText "Edit"}
(JMenuItem {:setText "Cut" :addActionListener (actionListener (fn
[e] (println "You clicked Cut")))})
(JMenuItem {:setText "Paste" :addActionListener (actionListener (fn
[e] (println "You clicked Paste")))}))))]

(. (gui 'frame) setJMenuBar (gui 'menubar))
(. (gui 'panel) setLayout (gui 'layout))
(. (gui 'frame) setVisible true)
(. (gui 'btn) addActionListener (actionListener (fn [e] (. (gui
'frame) setVisible false)))))

It works for the simple examples I've tried. It returns a map of
selected controls which you might need access to.

As Michael mentioned, getting the layout manager to do what you want
is difficult. I haven't used Swing before, so maybe this isn't
specific to using a declarative style.

I can't see a tidy way to let the components refer to each other
within the definition which might be handy, and as you can see it's
pretty verbose even for simply windows. Some parts could be shortened
with some extra macro - menu's in particular, but I'm starting to
think UI code is going to look pretty ugly unless you drastically
limit the options for customisation - there's just too many widgets
with too may variables involved.

And I haven't even thought about using the UI once it's been
constructed.

Martin DeMello

unread,
Oct 13, 2008, 7:39:09 PM10/13/08
to Clojure
On Oct 13, 12:37 pm, JumpingJupiter <jonathon.schofi...@gmail.com>
wrote:
> pretty verbose even for simply windows. Some parts could be shortened
> with some extra macro - menu's in particular, but I'm starting to
> think UI code is going to look pretty ugly unless you drastically
> limit the options for customisation - there's just too many widgets
> with too may variables involved.

Yeah, it does pretty much always seem to turn ugly, no matter what you
do :( I've lately been leaning towards the "define your widgets, then
lay them out" style, rather than customising inline in the layout. The
chicken bb egg has some other interesting ideas [http://
chicken.wiki.br/bb] but even there it ends up looking ugly sooner or
later.

Another way to go is the "design your gui in a gui designer, then
connect code to the resulting interface file" method, which I've seen
Ruby/(Qt, Gtk, Swing) projects use with decent success. In particular
the developers of Monkeybars (JRuby/Swing) project have come out and
said that manually laying out widgets in code is counterproductive.

What did look very promising was the approach taken by the Chicken/Qt
egg, which has widget constructors take a UIXML string (as generated
by QtDesigner) to instantiate themselves. In theory, that should let
you build up an application-specific rich widget collection quickly
and easily, then manipulate it from code, and also work on SXML->UIXML
methods that would let you generate widgets programmatically. I had
problems getting the egg up and running, though (this was a few years
ago), and used PLT instead, but when I have the free time I plan to go
take another look at it.

martin

Randall R Schulz

unread,
Oct 13, 2008, 7:50:47 PM10/13/08
to clo...@googlegroups.com
On Monday 13 October 2008 16:39, Martin DeMello wrote:
> On Oct 13, 12:37 pm, JumpingJupiter <jonathon.schofi...@gmail.com>
>
> wrote:
> > pretty verbose even for simply windows. Some parts could be
> > shortened with some extra macro - menu's in particular, but I'm
> > starting to think UI code is going to look pretty ugly unless you
> > drastically limit the options for customisation - there's just too
> > many widgets with too may variables involved.
>
> Yeah, it does pretty much always seem to turn ugly, no matter what
> you do :( I've lately been leaning towards the "define your widgets,
> then lay them out" style, rather than customising inline in the
> layout. The chicken bb egg has some other interesting ideas [http://
> chicken.wiki.br/bb] but even there it ends up looking ugly sooner or
> later.

I've done rather little GUI programming in my day (it doesn't appeal to
me), but I've been hearing about JavaFX lately and just today took a
quick look at what it's all about (someone on one of the IDEA forums
suggested it will ultimately take the place of Swing, and that got me
curious).

So I'm wondering, how does JavaFX factor into matters of GUI programming
and good APIs and frameworks to facilitate it?


> ...


Randall Schulz

V.Quixote

unread,
Oct 14, 2008, 6:00:40 PM10/14/08
to Clojure
It sounds like all we really need is a single clojure thread which
handles all access to Swing/AWT/Whatever. Since an additional
complaint is that Swing is too imperative, it sounds like both
problems could easily be solved at once.
I'd personally like for the declarations to be done using Clojure data
structures.
Reply all
Reply to author
Forward
0 new messages