Coming from LISP I am having my most challenging moments when accessing java objects. I am trying to put a titled border on a JPanel. Here is my code and exception:
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)>
Where can I find rules to deal with this kind of situations? As always your help will be highly appreciated.
I thank you all for your answers and clarifications. I am posting the basics of the function so we can all know what to refer to:
(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))))
Like that the function works no problem but what I am trying to do is to put a TitledBorder on panel_0. Following your instructions I have tried to code in different ways but not success so far.
Thanks again to you all for your help.
UPDATE:Sorry googloplex. With all this mess I was running a different defn. Yes it works as you and Kugathasan said. I finally coded as:
....
(JButton. "Button3") [:align "center"]
)
tb (BorderFactory/createTitledBorder "Title")
frame (JFrame. "Frame")
]
(.setBorder panel_0 tb)
(doto frame
....
and IT WORKED !!! Thank you all for dedicating your time to this.
Clojure language reference here gives the java interoperability rules pretty well. Here are the main points:
Static methods are called just like plain functions using class name as namespace:
(System/getProperty "java.class.path")
This will be resolved to java call System.getProperty("java.class.path")
Regular methods are called on specific objects of the class, so their calling syntax is slightly different:
(.setText label "Some text")
This will be resolved to java call label.setText("Some text")
. That is, the regular method calls take this form:
(.methodName object arg1 arg2 arg3 ...)
Object are constructed using special form new
:
(new JLabel "Initial text")
There is a shorthand for it using dot reader macro:
(JLabel. "Initial text")
These last two forms are completely equivalent. So, as you can see, construction takes this form:
(new Classname arg1 arg2 ...)
; or
(Classname. arg1 arg2 ...)
Of course, to use regular methods you have to bind newly created object to some symbol, e.g. like this:
(let [label (JLabel. "Initial text")]
...)
Inside let
body you now can use label
as an object:
(let [label (JLabel. "Initial text")]
(.setText label "New text")
(.setIconTextGap label 10))
As follows from your code in the commentary to Kugathasan Abimaran's answer, you are trying to use the same JPanel in several places. You are doing it incorrectly, since (see #3 above) (JPanel. ...)
is a construction form, it returns new object every time you use it. You have to bind the new object to some variable, then call methods on it and then put it into container/whatever you need.
UPDATE:
Your code is fine, you should do like Kugathasan Abimaran suggested. Add his code just before your (doto frame ...
line, replacing (JPanel.)
there with your panel_0
. It will work as required.