Created
August 9, 2009 07:18
-
-
Save radhikalism/164652 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns slider-demo | |
"A brief demonstration of using interactive Swing components with Clojure." | |
(:import [javax.swing JSlider JFrame JPanel SwingConstants] | |
[javax.swing.border LineBorder] | |
[javax.swing.event ChangeListener] | |
[java.awt BorderLayout Color Rectangle])) | |
(defn make-frame | |
"Returns a JFrame instance which is non-resizable, 800px wide, 600px high, | |
and containing panel." | |
[panel] | |
(let [frame (new JFrame)] | |
(doto frame | |
(.setResizable false) | |
(.setSize 800 600) | |
(.add panel) | |
(.show)))) | |
(defn make-content | |
"Returns a JPanel instance using BorderLayout, and containing plot and | |
vertical and horizontal slider controls." | |
[plot slider-x slider-y] | |
(let [content (new JPanel)] | |
(doto content | |
(.setBackground Color/BLACK) | |
(.setLayout (new BorderLayout 10 10)) | |
(.add slider-x BorderLayout/SOUTH) | |
(.add slider-y BorderLayout/WEST) | |
(.add plot)))) | |
(defn make-plot | |
"Returns a styled JPanel instance that serves as a drawing area, rendered | |
by invoking paint-fn from paintComponent, with a cleared Graphics object." | |
[paint-fn] | |
(let [plot (proxy [JPanel] [] | |
(paintComponent [graphics] | |
(proxy-super paintComponent graphics) | |
(paint-fn graphics)))] | |
(doto plot | |
(.setBackground Color/BLACK)))) | |
(defn make-slider | |
"Returns a JSlider instance oriented along axis, and with an added | |
ChangeListener that invokes state-changed-fn on change events." | |
[axis state-changed-fn] | |
(let [orientation (axis {:x SwingConstants/HORIZONTAL, | |
:y SwingConstants/VERTICAL}) | |
initial (axis {:x 0, :y 100}) | |
slider (new JSlider orientation 0 100 initial) | |
listener (proxy [ChangeListener] [] | |
(stateChanged [e] (state-changed-fn e)))] | |
(doto slider | |
(.setBackground Color/BLACK) | |
(.addChangeListener listener)))) | |
(defn paint-plot | |
"Renders spot on a cleared Graphics object." | |
[spot graphics] | |
(doto graphics | |
(.setColor Color/DARK_GRAY) | |
(.fillRect @(:x spot) @(:y spot) (:size spot) (:size spot)) | |
(.setColor Color/GREEN) | |
(.drawRect @(:x spot) @(:y spot) (:size spot) (:size spot)))) | |
(defn update-spot | |
"Repaints plot with the recalculated and reset position of spot in plot, | |
according to the value of event's source slider." | |
[axis spot plot event] | |
(let [ratio (/ (.getValue (.getSource event)) 100) | |
ratio (if (= :y axis) (- 1 ratio) ratio) | |
range (if (= :y axis) (.getHeight plot) (.getWidth plot)) | |
range (- range (+ 2 (:size spot))) | |
position (int (* ratio range))] | |
(reset! (axis spot) position) | |
(.repaint plot))) | |
(defn main | |
"Draws a frame with two sliders that control the vertical and horizontal | |
position of a box in a drawing area." | |
[] | |
(let [spot {:x (atom 0) :y (atom 0) :size 8} | |
plot (make-plot (partial paint-plot spot)) | |
slider-x (make-slider :x (partial update-spot :x spot plot)) | |
slider-y (make-slider :y (partial update-spot :y spot plot)) | |
content (make-content plot slider-x slider-y) | |
frame (make-frame content)] | |
{:frame frame | |
:content content | |
:slider-x slider-x | |
:slider-y slider-y | |
:plot plot | |
:spot spot})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment