0
votes

I have adapted this method from p.216 Joy of Clojure.

 (defn makeButton [txt func panel]
    (let [btn (JButton. txt) ] ;bfun (symbol func) ]
    (doto  btn
        (.addActionListener 
            (proxy [ActionListener] [] (actionPerformed [_] 
                (func))) ;(bfun)))
        ))
        (.add panel btn)
    ))

Plus this test code:

(defn fba [] (prn "fba"))
(defn fbb [] (prn "fbb"))
(def funs [fba fbb])
(def btnames ["B1" "B2"])

Buttons & actionPerformed are created thusly in a gui setup function:

(doseq [i (range (count btnames)) ] 
              (makeButton (get btnames i) (nth funs i) aJpanel))

This works as I want; clicking "B1" prints string "fba", etc. My difficulty arises when I want to attach to 'actionPerformed' something such as: ns1.ns2/myFunction instead of these simple cases (i.e. use a list/vector of several namespaced qualified functions). The exception reported is

wrong number of args (0) passed to Symbol

From the 'makeButton' function above my attempt to solve this is commented out. What is an idiomatic clojure solution to this?

1
All you should need to do is replace one of the functions in funs with ns1.ns2/myFunction. If you try that (without modifying makeButton from the working version) what happens? - Shepmaster
As an aside, I'd recommend using a map for your labels / functions: (def foo {"B1" fba, "B2" fbb}) and then make your buttons as (doseq [[label f] foo] (make-button label f panel)) - Shepmaster
Thank you for useful advice on use of map. Sometimes one returns to old Java loop habits. - Brian
No worries, I'm still learning Clojure myself, so I try to find code that doesn't look "Clojure-like". :-) - Shepmaster

1 Answers

1
votes

This code works for me in the REPL. I'm using clojure.pprint/pprint as an example of a function that is in a different namespace:

(import '[javax.swing JFrame JPanel JButton]
        '[java.awt.event ActionListener])

(def panel (JPanel.))

(def frame (doto (JFrame. "Hello Frame")
             (.setContentPane panel)
             (.setSize 200 200)
             (.setVisible true)))

(defn make-button [label f panel]
  (let [button (JButton. label)]
    (doto button
      (.addActionListener
       (proxy [ActionListener] []
         (actionPerformed [evt]
           (f evt)))))
    (.add panel button)))

(make-button "One" clojure.pprint/pprint panel)

(.revalidate frame)