there! I'm building an image-processing application in swing/clojure, and right now I need to develop an image panel in which I can click and compute data. Thanks to coobird, I now have a good idea on how to do it in Java, but I still don't get many issues on its integration with Clojure.
Let's take a look at how coobird suggested me doing. First, we should extend a class in Java. In clojure, we do this with the proxy
macro, so we'd have something like this:
(def painting-panel (proxy [JPanel] []))
The next step is to create the class constructor and set some variables.
I can define functions after the second argument of proxy, but how can I create the constructor? Is painting-panel the name of this class (therefore the name of the function I should create)?
How can I deal with class variables? Should I define them with a let
, like I did?
Are this
and super
available for me to use, like I did below?
(def painting-panel (let [background-image (Image.) point-clicked (Point.)] (proxy [JPanel] [] (paintComponent [g] (do ((.paintComponent super) g) (doto g (.drawImage background-image 0 0 nil) (.fillRect (.x point-clicked) (.y point-clicked) 1 1)))) (painting-panel []; constructor? ((.addMouseListener this) (proxy [MouseAdapter] [] (mouseClicked [e] (do (def point-clicked (.getPoint e)) (.repaint this)))))))))
Suggestions and code corrections are also welcome!
Thank you!
proxy actually creates an instance tada! You don't need to create a constructor.
Yes, but consider using a clojure ref instead. Also using def like that on the second last line is nasty! it creates a global binding for point-clicked when your logic relies on the lexically scoped one created by let.
(proxy-super paintComponent g), and yes "this" is available
This works for me:
(let [click (ref nil)
panel (proxy [javax.swing.JPanel] []
(paintComponent [g]
(proxy-super paintComponent g)
(.drawImage g (.getImage
(javax.swing.ImageIcon. "play.png"))
0 0 (.getWidth this) (.getHeight this) nil)
(if @click
(.fillRect g (:x @click) (:y @click) 10 10))))]
(.addMouseListener panel
(proxy [java.awt.event.MouseAdapter] []
(mouseClicked [e]
(let [p (.getPoint e)]
(dosync (ref-set click {:x (.x p), :y (.y p)})))
(javax.swing.SwingUtilities/invokeLater #(.repaint panel)))))
(doto (javax.swing.JFrame.)
(.setContentPane panel)
(.setSize 200 200)
(.show)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With