Clojure добавление границы в JPanel и вообще доступ к java-методам в объектах

Исходя из LISP, у меня самые сложные моменты при доступе к Java-объектам. Я пытаюсь поставить титулованную границу на JPanel. Вот мой код и исключение:

user=> (import '(javax.swing JComponent JPanel BorderFactory))
javax.swing.BorderFactory
user=> (JPanel. (.setBorder (.createTitledBorder "Title")))
#<CompilerException java.lang.IllegalArgumentException: No matching field found: createTitledBorder for class java.lang.String (NO_SOURCE_FILE:785)>

Где я могу найти правила для решения таких ситуаций? Как всегда, ваша помощь будет высоко оценена.

Я благодарю вас всех за ваши ответы и разъяснения. Я публикую основы этой функции, чтобы мы все знали, к чему обращаться:

(import '(javax.swing JComponent JButton JFrame JLabel JPanel BorderFactory))
(use '(clojure.contrib [miglayout :only (miglayout)]))

(defn cm_dlg []
  (let
    [
     panel_0
     (miglayout
       (JPanel.)
       :layout  [:wrap 2]
       (JLabel. "Some Text:") [:align "right"]
       (JLabel. "More Text:") [:align "left"]
       (JLabel. "Some Text:") [:align "right"]
       (JLabel. "More Text:") [:align "left"]
       (JLabel. "Some Text:") [:align "right"]
       (JLabel. "More Text:") [:align "left"]
       (JLabel. "Some Text:") [:align "right"]
       (JLabel. "More Text:") [:align "left"]
       )
     panel_1
     (miglayout 
       (JPanel.)
       :layout  [:wrap]
       (JButton. "Button0") [:align "center"]
       (JButton. "Button1") [:align "center"]
       (JButton. "Button2") [:align "center"]
       (JButton. "Button3") [:align "center"]
       )
     frame (JFrame. "Frame")
     ]
    (doto frame
      (.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
      (-> .getContentPane
        (.add (miglayout (JPanel.)
                :layout [:flowy]
                panel_0 [:align "center"]
                panel_1 [:align "center"]
                )))
      (.pack)
      (.setVisible true)))) 

Например, эта функция работает без проблем, но я пытаюсь установить TitledBorder на panel_0. Следуя вашим инструкциям, я пытался кодировать по-разному, но пока безуспешно.
Еще раз спасибо всем за вашу помощь.

ОБНОВЛЕНИЕ: Извините, гуглоплекс. Со всем этим беспорядком у меня была другая защита. Да, это работает, как ты и Кугатасан сказали. Я наконец закодировал как:

....
   (JButton. "Button3") [:align "center"]
   )
     tb (BorderFactory/createTitledBorder "Title")
     frame (JFrame. "Frame")
     ]
    (.setBorder panel_0 tb)
    (doto frame
....

И ЭТО РАБОТАЛО!!! Спасибо всем за то, что посвятили этому время.

3 ответа

Решение

Справочник по языку Clojure очень хорошо описывает правила взаимодействия с Java. Вот основные моменты:

  1. Статические методы вызываются как обычные функции, используя имя класса в качестве пространства имен:

    (System/getProperty "java.class.path")
    

    Это будет решено для вызова Java System.getProperty("java.class.path")

  2. Обычные методы вызываются для определенных объектов класса, поэтому их синтаксис вызова немного отличается:

    (.setText label "Some text")
    

    Это будет решено для вызова Java label.setText("Some text"), То есть обычные вызовы методов имеют такую ​​форму:

    (.methodName object arg1 arg2 arg3 ...)
    
  3. Объект строится с использованием специальной формы new:

    (new JLabel "Initial text")
    

    Для этого есть сокращение, использующее макрос для чтения точек:

    (JLabel. "Initial text")
    

    Эти последние две формы полностью эквивалентны. Итак, как вы можете видеть, конструкция принимает следующую форму:

    (new Classname arg1 arg2 ...)
    ; or
    (Classname. arg1 arg2 ...)
    

Конечно, чтобы использовать обычные методы, вы должны привязать вновь созданный объект к некоторому символу, например, так:

(let [label (JLabel. "Initial text")]
  ...)

внутри let тело вы можете использовать label как объект:

(let [label (JLabel. "Initial text")]
  (.setText label "New text")
  (.setIconTextGap label 10))

Как следует из вашего кода в комментарии к ответу Кугатасана Абимарана, вы пытаетесь использовать один и тот же JPanel в нескольких местах. Вы делаете это неправильно, так как (см. № 3 выше) (JPanel. ...) это строительная форма, она возвращает новый объект каждый раз, когда вы его используете. Вы должны связать новый объект с некоторой переменной, затем вызвать методы для него и затем поместить его в контейнер / все, что вам нужно.

ОБНОВЛЕНИЕ: Ваш код в порядке, вы должны делать то, что предложил Кугатасан Абимаран. Добавьте его код прямо перед вашим (doto frame ... линия, заменяющая (JPanel.) там с вашим panel_0, Это будет работать как требуется.

Вы можете попытаться сделать это следующим образом, неправильный способ доступа к Java в Clojure.

(.setBorder (JPanel.) (BorderFactory/createTitledBorder "Title"))

Вы можете прочитать ссылки на Java-взаимодействия, чтобы узнать, как получить доступ к Java в Clojure.

Какой код Java вы пытаетесь воспроизвести? Похоже, вы могли бы хотеть BorderFactory/createTitledBorder а кто знает?

Другие вопросы по тегам