2009-10-05 42 views
7

那里!我在swing/clojure中构建了一个图像处理应用程序,现在我需要开发一个图像面板,在该面板中我可以点击并计算数据。感谢coobird,我现在对如何在Java中实现这个想法有了一个很好的想法,但是我仍然没有在与Clojure集成方面遇到很多问题。图像处理,在Clojure中扩展JPanel和模拟类

让我们来看看coobird如何建议我这样做。首先,我们应该用Java扩展一个类。 Clojure中,我们这样做与proxy宏,所以我们希望有这样的事情:

 
(def painting-panel 
    (proxy [JPanel] [])) 

下一步是创建类的构造函数,并设置一些变量。

  1. 我可以在代理的第二个参数后面定义函数,但是如何创建构造函数呢?绘画面板是这个类的名称(因此我应该创建函数的名称)?

  2. 我该如何处理类变量?我应该像let那样定义它们,就像我一样吗?

  3. thissuper可供我使用,就像我下面做的那样?

 
(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))))))))) 

建议和代码更正也欢迎!

谢谢!

回答

8
  1. proxy实际上创建了一个实例tada!您不需要创建构造函数。

  2. 是的,但考虑使用clojure ref。在第二行最后使用def也是一件令人讨厌的事情!它会创建一个全局绑定点,当你的逻辑依赖于由let创建的词法范围的逻辑。

  3. (代理超强的paintComponent克),是 “本” 可

这个工作对我来说:

(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))) 
+1

我爱你,伙计们。认真。 – konr 2009-10-05 21:53:11

+3

我也爱你。 – 2010-01-14 01:46:38