(some #{:easy :simple} swing)
;=> nil
JLabel myLabel = new JLabel("Hiya");
myLabel.setBackground(new Color(136, 136, 136));
myLabel.setOpaque(true);
myLabel.setForeground(Color.BLUE);
JFrame myFrame = new JFrame("Why Swing, why?");
myFrame.setContent(myLabel);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.pack();
myFrame.setVisible(true);
(doto (JFrame. "Why Swing, why?")
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.setContent (doto (JLabel. "Hiya")
(.setBackground (Color. 136 136 136))
(.setOpaque true)
(.setForeground Color/BLUE)))
.pack
(.setVisible true))
(-> (frame :title "Why Swing, why?"
:on-close :exit
:content (label :text "Hiya"
:border 5
:background "#888"
:foreground :blue))
pack!
show!)
:red
"#F00"
"#FF0000"
:my-app.core/my-color-resource
"ARIAL-BOLD-18"
{:name "ARIAL" :style :bold :size 18}
(seesaw.font/font :name "ARIAL"
:style :bold
:size 18)
:my-app.core/my-font-resource
"http://example.com/icon.png"
(clojure.java.io/resource "path/to/icon.png")
:my-app.core/my-icon-resource
; Keystroke
"ctrl C"
; Dimensions
[640 :by 480]
; Borders
[5 "Compound" 10]
(config! my-label :background :red
:foreground "#00FF00")
;=> my-label
(config my-label :background)
;=> #<Color java.awt.Color[r=255,g=0,b=0]>
(value (textbox :text "HI"))
;=> "HI"
(value (slider :min 0 :max 11 :value 6))
;=> 6
(-> (combobox :model [1 2 3 4])
(selection! 3)
value)
;=> 3
(def form
(grid-panel :columns 2
:items ["First Name" (text :id :first-name)
"Last Name" (text :id :last-name)
"Sex" (combobox :id :sex
:model ["Female" "Male"])
"Age" (spinner :id :age)]))
(-> (dialog :content form) pack! show!)
;=> :success
(value form)
=> {:first-name "Philip",
:last-name "Glass",
:sex "Male",
:age 75}
public interface MouseListener {
void mouseClicked(MouseEvent e);
void mouseEntered(MouseEvent e);
void mouseExited(MouseEvent e);
void mousePressed(MouseEvent e);
void mouseReleased(MouseEvent e);
}
JLabel label = new JLabel();
label.addMouseListener(new MouseListener() {...});
(.addMouseListener my-panel
(proxy [MouseAdapter] []
(mouseClicked [this e]
... do something ...)))
(.addMouseMotionListener my-panel
(proxy [MouseMotionAdapter] []
(mouseMoved [this e]
... do something ...)))
(.addComponentListener my-panel
(proxy [ComponentAdapter] []
(componentResized [e]
... do something ...)))
(listen my-panel
:mouse-clicked (fn [e] ... do something ...)
:mouse-moved (fn [e] ... do something ...)
:component-resized (fn [e] ... do something))
:selection
// List
JList myList = ...;
myList.addListSelectionListener(...);
(listen my-list :selection (fn [e] ...))
:selection
// Tree
JTree myTree = ...;
myTree.addTreeSelectionListener(...);
// seriously?
(listen my-tree :selection (fn [e] ...))
:selection
// Table
JTable myTable = ...;
myTable.getListSelectionModel()
.addListSelectionListener(...);
// oh, come on.
(listen my-table :selection (fn [e] ...))
// Group of mutually exclusive radio buttons
Enumeration<AbstractButton> bs =
myButtons.getElements();
for(; bs.hasMoreElements();) {
bs.nextElement().addItemListener(...);
}
// WTF, eh?
(listen buttons :selection (fn [e] ...))
(require '[seesaw.bind :as b])
(def safety (checkbox :text "Safety"
:selected? false))
(def fire-missiles (button :text "Fire!"
:enabled? false))
(b/bind
safety
(property fire-missiles :enabled?))
...
(def status (label :text "Safe"))
(b/bind
safety
(b/tee
(property fire-missiles :enabled?)
(b/bind
(b/transform #(if % :red :green))
(property status :background))
(b/bind
(b/transform #(if % "Armed" "Safe"))
(property status :text))))
(def volume-control (slider :min 0 :max 11 :value 5))
(def volume-atom (atom 5))
(b/bind volume-control
volume-atom
volume-control)
How do you separate layout from behavior?
Select by :id
(select panel [:#first-name])
;=> JTextField
Select by :class
(select panel [:.dangerous])
;=> (JButton JButton JButton ...)
Select all children of widget with class :foo
(select root [:.foo :> :*])
... and many, more
Plays nicely with "vectorized" config!
; Disable everything
(config! (select panel [:*]) :enabled? false)
Plays nicely with "vectorized" listen
; Add action handler to all widgets
; with class :dangerous
(listen (select panel [:.dangerous])
:action (fn [e] ...))
(button :id :open-doors :text "Open Pod Bay Doors")
(checkbox :id :safety :text "Safety")
(button :id :launch-missiles :class ...)
(button :id :fire-torpedoes :class :dangerous ...)
...
(defn add-behaviors [root]
(listen (select root [:#open-doors]) :action
(fn [_] ...))
(listen (select root [:#safety]) :selection
(fn [e]
(config! (select root [:.dangerous])
:enabled? (not (selection e)))))
...
"Seesaw is amazing and wonderful, but it still doesn't do much good for people who don't know Java/Swing already"Anthony Grimes (aka Raynes)
user=> (doc button)
-------------------------
seesaw.core/button
([& args])
Construct a generic button. In addition to default widget options, supports
the following:
:halign Horizontal alignment. One of :left, :right, :leading, :trailing,
:center
... snip ...
Resources and i18n:
A button's base properties can be set from a resource prefix, i.e. a namespace-
qualified keyword that refers to a resource bundle loadable by j18n.
Examples:
; Create a button with text "Next" with alt-N mnemonic shortcut that shows
; an alert when clicked.
(button :text "Next"
:mnemonic \N
:listen [:action #(alert "NEXT!")])
See:
http://download.oracle.com/javase/6/docs/api/javax/swing/JButton.html
(seesaw.core/button-group)
(use 'seesaw.dev)
user=> (show-options (label))
Option Notes/Examples
------------------- --------------
:background :aliceblue
"#f00"
"#FF0000"
(seesaw.color/color 255 0 0 0 224)
:border 5
"Border Title"
[5 "Compound" 10]
See (seesaw.border/*)
:bounds :preferred
[x y w h]
Use :* to leave component unchanged:
... snip a lot here...
:user-data Anything.
Associate arbitrary user-data with a widget.
See (seesaw.core/user-data)
:v-text-position :bottom
:center
:top
:valign :bottom
:center
:top
:visible? boolean
user=> (show-events (text))
:action [java.awt.event.ActionListener]
:action-performed
:caret [javax.swing.event.CaretListener]
:caret-update
:component [java.awt.event.ComponentListener]
:component-hidden
:component-moved
:component-resized
:component-shown
... snip a lot here ...
:mouse-motion [java.awt.event.MouseMotionListener]
:mouse-dragged
:mouse-moved
:mouse-wheel [java.awt.event.MouseWheelListener]
:mouse-wheel-moved
:property-change [java.beans.PropertyChangeListener]
:property-change
:selection [javax.swing.event.CaretListener]
:caret-update
; Construct a widget
(def my-text (text :id :my-text :text "Hi" :font ...))
;=> #<JLabel ...>
; Change a widget
(config! my-text :enabled? false)
;=> #<JLabel ...>
; Get a widget's value
(value my-text)
;=> "Hi"
; Find out when things happen
(listen my-text :focus-gained (fn [e] ...))
; Bind widgets together
(bind my-text (property my-label :text))
; Find a widget
(select root [:#my-text])
;=> <JLabel ...>
; Explore a widget
(show-options my-text)
(show-events my-text)
Use a spacebar arrow keys to navigate