Обработка изображений, расширение JPanel и моделирование классов в Clojure - PullRequest
7 голосов
/ 05 октября 2009

есть! Я создаю приложение для обработки изображений в режиме Swing / Clojure, и сейчас мне нужно разработать панель изображений, в которой я могу щелкать и вычислять данные. Благодаря coobird у меня теперь есть хорошая идея о том, как сделать это в Java, но у меня до сих пор не возникает проблем с его интеграцией с Clojure.

Давайте посмотрим, как coobird предложил мне это сделать. Во-первых, мы должны расширить класс в Java. В clojure, мы делаем это с макросом proxy, поэтому у нас будет что-то вроде этого:

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

Следующим шагом является создание конструктора класса и установка некоторых переменных.

  1. Я могу определять функции после второго аргумента прокси, но как я могу создать конструктор? Является ли painting-панель названием этого класса (поэтому имя функции, которую я должен создать)?

  2. Как мне работать с переменными класса? Должен ли я определить их с помощью let, как я сделал?

  3. Могу ли я использовать this и super, как я делал ниже?

(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 Ответ

8 голосов
/ 05 октября 2009
  1. прокси фактически создает экземпляр tada! Вам не нужно создавать конструктор.

  2. Да, но вместо этого рассмотрите возможность использования ссылки clojure. Также использовать def, как это во второй последней строке, неприятно! он создает глобальную привязку для нажатой точки, когда ваша логика основана на лексической области действия, созданной let.

  3. (proxy-super paintComponent g), и да, "this" доступно

Это работает для меня:

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