I am writing code to fill a java.awt.GridBagLayout with "rows" 开发者_StackOverflow社区of controls. For each row, I have a method call of the form
(.add panel CONTROL (fill-gbc 0 INDEX ...))
where CONTROL is the Swing control to place at this row (i.e.: (JLabel. "Hello")
) and INDEX is the gridy
for that control (fill-gbc
fills a single, mutable, GridBagContraints
object and returns it -- it accepts keyword optional parameters for gridwidth
, gridheight
, etc.)
I would like to create a vector of the row contents (the (.add panel ...)
calls) and use (map-indexed ...)
to fill in the INDEX value.
The only way that I can come up with do do this is to make each (.add panel ...)
an anonymous function of one parameter (the index):
(dorun (map-indexed #(%2 %1)
[#(.add panel (.JLabel "Hello") (fill-gbc 0 %)) ...]))
Is there a better way to do this, perhaps with a macro (I'll need this pattern several times in my application for various dialog boxes)?
You could abstract this away into a function, then you can use it wherever you need it.
(defn add-on-row [panel c]
(dorun
(map-indexed
#(%2 %1)
[#(.add panel c (fill-gbc 0 %)) ...])))
You'd just pass parameters for whatever information will ever vary.
Furthermore, I wrote a little macro for adding a bunch of things to a container.
(defmacro add [cmp & things]
(cons
'do
(for [thing things]
`(.add ~cmp ~@(if (vector? thing) thing [thing])))))
That let's you write stuff like this:
(add
panel
[(JLabel. "Hello") "more arguments"]
(JLabel "Hello!"))
Not sure if that's helpful for you in this situation, but it might be.
精彩评论