What is the best way to do GUIs in Clojure?
Is there an example of some functional Swing or SWT wrapper? Or some integration with JavaFX declarative GUI description
There is a wrapper for MigLayout in clojure contrib. You can also take a look at this gist. I am basically putting up whatever code I am writing as I am learning swing/miglayout.
dsm's example re-written in a lispy way using contrib.swing-utils
(ns test
(:import (javax.swing JButton JFrame))
(:use (clojure.contrib
[swing-utils :only (add-action-listener)])))
(defn handler
[event]
(JOptionPane/showMessageDialog nil,
(str "<html>Hello from <b>Clojure</b>. Button "
(.getActionCommand event) " clicked.")))
(let [ frame (JFrame. "Hello Swing")
button (JButton. "Click Me") ]
(add-action-listener button handler)
(doto frame
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.add button)
(.pack)
(.setVisible true)))
I will humbly suggest Seesaw.
Here's a REPL-based tutorial that assumes no Java or Swing knowledge.
Seesaw's a lot like what @tomjen suggests. Here's "Hello, World":
(use 'seesaw.core)
(-> (frame :title "Hello"
:content "Hello, Seesaw"
:on-close :exit)
pack!
show!)
and here's @Abhijith and @dsm's example, translated pretty literally:
(ns seesaw-test.core
(:use seesaw.core))
(defn handler
[event]
(alert event
(str "<html>Hello from <b>Clojure</b>. Button "
(.getActionCommand event) " clicked.")))
(-> (frame :title "Hello Swing" :on-close :exit
:content (button :text "Click Me" :listen [:action handler]))
pack!
show!)
My preferred Clojure UI environment uses IO.js (Node for ES6) + Electron (Container) + Quiescent (ReactJS wrapper).
There's been talk on the mailing list about a few Cells (a la Kenny Tilton's Cells) implementations. It's a pretty neat way to do GUI programming.
Stuart Sierra recently published a series of blog posts on GUI-development with clojure (and swing). Start off here: http://stuartsierra.com/2010/01/02/first-steps-with-clojure-swing
From this page:
(import '(javax.swing JFrame JButton JOptionPane)) ;'
(import '(java.awt.event ActionListener)) ;'
(let [frame (JFrame. "Hello Swing")
button (JButton. "Click Me")]
(.addActionListener button
(proxy [ActionListener] []
(actionPerformed [evt]
(JOptionPane/showMessageDialog nil,
(str "<html>Hello from <b>Clojure</b>. Button "
(.getActionCommand evt) " clicked.")))))
(.. frame getContentPane (add button))
(doto frame
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
.pack
(.setVisible true)))
print("code sample");
And, of course, it would be worth looking at the interoperability section of clojure's website.