0

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?

4
  • 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? Commented Feb 12, 2014 at 15:47
  • 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)) Commented Feb 13, 2014 at 12:45
  • Thank you for useful advice on use of map. Sometimes one returns to old Java loop habits. Commented Feb 14, 2014 at 11:38
  • No worries, I'm still learning Clojure myself, so I try to find code that doesn't look "Clojure-like". :-) Commented Feb 14, 2014 at 11:44

1 Answer 1

1

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)
Sign up to request clarification or add additional context in comments.

1 Comment

Very strange, but you are correct, your version works. Thank you for helping. Now I have to determine where I messed up.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.