图像处理,在Clojure中扩展JPanel和模拟类

时间:2009-10-05 09:01:09

标签: swing lisp clojure

有!我正在使用swing / clojure构建一个图像处理应用程序,现在我需要开发一个图像面板,我可以在其中单击并计算数据。感谢coobird,我现在对如何使用Java做了很好的想法,但我仍然没有在与Clojure的集成方面遇到很多问题。

让我们来看看coobird如何建议我这样做。首先,我们应该在Java中扩展一个类。在clojure中,我们使用proxy宏执行此操作,因此我们将使用以下内容:

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

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

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

  2. 如何处理类变量?我应该像{I}一样用let来定义它们吗?

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

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

    欢迎提出建议和代码更正!

    谢谢!

1 个答案:

答案 0 :(得分:8)

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

  2. 是的,但请考虑使用clojure ref。在最后一行使用def就像是那样令人讨厌!当你的逻辑依赖于let创建的词法范围时,它会创建一个用于点击的全局绑定。

  3. (proxy-super paintComponent g),是的“这个”可用

  4. 这对我有用:

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