Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6096335
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T12:54:56+00:00 2026-05-23T12:54:56+00:00

I am working on a Clojure macro to help build GridBagLayout-based JPanels. I can

  • 0

I am working on a Clojure macro to help build GridBagLayout-based JPanels. I can get Java classes in a defaults map inside the macro to namespace-qualify, but not those passed in as arguments. What magic combination of backquotes, quotes, tildas, or something else do I need?

(import [java.awt GridBagConstraints GridBagLayout Insets]
        [javax.swing JButton JPanel])

(defmacro make-constraints [gridx gridy & constraints]
  (let [defaults
        {:gridwidth 1 :gridheight 1 :weightx 0 :weighty 0
         :anchor 'GridBagConstraints/WEST :fill 'GridBagConstraints/NONE
         :insets `(Insets. 5 5 5 5) :ipadx 0 :ipady 0}

        values
        (assoc (merge defaults (apply hash-map constraints))
          :gridx gridx :gridy gridy)]
    `(GridBagConstraints. ~@(map (fn [value]
                                   (if
                                    (or
                                     (number? value)
                                     (string? value)
                                     (char? value)
                                     (true? value)
                                     (false? value)
                                     (nil? value))
                                    value
                                    `~value))
                                 (map values
                                      [:gridx :gridy :gridwidth :gridheight
                                       :weightx :weighty :anchor :fill
                                       :insets :ipadx :ipady])))))

When I use the Insets defined in the defaults map, it gets qualified (not “symbol-captured”) as (java.awt.Insets ...):

user=> (macroexpand-1 '(make-constraints 0 0 :weightx 1))
(java.awt.GridBagConstraints.
 0 0 1 1 1 0
 GridBagConstraints/WEST GridBagConstraints/NONE
 (java.awt.Insets. 5 5 5 5) 0 0)

but when I pass it as an argument, it does not:

user=> (macroexpand-1 '(make-constraints 1 1 :insets (Insets. 2 2 2 2)))
(java.awt.GridBagConstraints.
 1 1 1 1 0 0
 GridBagConstraints/WEST GridBagConstraints/NONE
 (Insets. 2 2 2 2) 0 0)

I’m not just trying to be a stickler. I am getting compiler errors that it cannot find a proper GridBagConstraints constructor.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T12:54:57+00:00Added an answer on May 23, 2026 at 12:54 pm

    Here is my solution. I am using it in a Swing application that I am writing. It has already saved me many lines of code writing (for two different panels) and will be as fast as hand-written code.

    (defmacro grid-bag-container [container & args]
      "Fill and return a java.awt.Container that uses the GridBagLayout.
      The macro defines a set of default constraints for the GridBagConstraints:
        :gridwidth 1
        :gridheight 1
        :weightx 0
        :weighty 0
        :anchor :WEST
        :fill :NONE
        :insets (Insets. 5 5 5 5)
        :ipadx 0
        :ipady 0
      These defaults can be overridden in the call to the macro in two way:
        - If the first argument is a hash-map of constraint names and values
          (e.g.: {:weightx 1}), these will override the defaults for the
          entire container.
        - Each individual item (see below) can override the global defaults
          and container defaults for itself.
      The constraints consist of constraint name (as a keyword with the same
      name as the GridBagConstraints field), and a value, which can also be
      a keyword, in which case the appropriate constant from GridBagConstraints
      will be substituted (e.g.: :NONE == GridBagConstraints.NONE), or the value
      can be an expression (e.g.: 0 or (Insets. 2 2 2 2)).
      Following the optional container default overrides hash-map are one or
      more row specification vectors. Each vector represents one row and
      increments gridy (starting from 0). Each vector contains one or more
      item vectors representing the individual components to be added to the
      container. Each item vector has the component as its first value,
      followed by zero or more constraint overrides as keyword-value pairs.
      (e.g.: [myButton :gridwidth 2 :weightx 1]). The values may be keywords
      and are expanded to GridBagConstraints constants as described above.
      Each item vector gets the next value of gridx (starting with 0) in that
      row.
      For example:
        (grid-bag-container panel
          {:insets (Insets. 1 1 1 1)}
          [[button :gridwidth 2 :weightx 1.0 :fill :HORIZONTAL]]
          [[check-box :gridwidth 2 :weightx 1.0 :anchor :CENTER]]
          [[arrive-label] [arrive-text-field :fill :HORIZONTAL]]
          [[depart-label] [depart-text-field :fill :HORIZONTAL]])
      will expand to the hand-written equivalent:
        (doto panel
          (.add button
            (GridBagConstraints. 0 0 2 1 1.0 0  ; gridx: 0 gridy: 1
                                 GridBagConstraints/WEST
                                 GridBagConstraints/HORIZONTAL
                                 (Insets. 1 1 1 1) 0 0))
          (.add check-box
            (GridBagConstraints. 0 1 2 1 1.0 0  ; gridx: 0 gridy: 1
                                 GridBagConstraints/CENTER
                                 GridBagConstraints/NONE
                                 (Insets. 1 1 1 1) 0 0))
          (.add arrive-label
            (GridBagConstraints. 0 2 1 1 0 0    ; gridx: 0 gridy: 2
                                 GridBagConstraints/WEST
                                 GridBagConstraints/NONE
                                 (Insets. 1 1 1 1) 0 0))
          (.add arrive-text-field
            (GridBagConstraints. 1 2 1 1 0 0    ; gridx: 1 gridy: 2
                                 GridBagConstraints/WEST
                                 GridBagConstraints/HORIZONTAL
                                 (Insets. 1 1 1 1) 0 0))
          (.add depart-label
            (GridBagConstraints. 0 3 1 1 0 0    ; gridx: 0 gridy: 3
                                 GridBagConstraints/WEST
                                 GridBagConstraints/NONE
                                 (Insets. 1 1 1 1) 0 0))
          (.add depart-text-field
            (GridBagConstraints. 1 3 1 1 0 0    ; gridx: 1 gridy: 3
                                 GridBagConstraints/WEST
                                 GridBagConstraints/HORIZONTAL
                                 (Insets. 1 1 1 1) 0 0))
      @param container the java.awt.Container to fill
      @param args the components and GridBagContraints speicifcations
      @returns the filled Container"
      (let [global-defaults
            {:gridwidth 1
             :gridheight 1
             :weightx 0
             :weighty 0
             :anchor :WEST
             :fill :NONE
             :insets `(Insets. 5 5 5 5)
             :ipadx 0
             :ipady 0}
    
            [defaults rows]
            (if (map? (first args))
              [(into global-defaults (first args)) (rest args)]
              [global-defaults args])]
        `(doto ~container
          ~@(loop [gridy 0 rows rows ret []]
            (if (seq rows)
              (recur (inc gridy) (rest rows)
                (into ret
                  (let [row (first rows)]
                    (loop [gridx 0 row row ret []]
                      (if (seq row)
                        (recur (inc gridx) (rest row)
                          (conj ret
                            (let [item
                                  (first row)
    
                                  component
                                  (first item)
    
                                  constraints
                                  (assoc (merge defaults
                                                (apply hash-map (rest item)))
                                    :gridx gridx :gridy gridy)
    
                                  constraint-values
                                  (map (fn [value]
                                    (if (keyword? value)
                                      `(. GridBagConstraints
                                          ~(symbol (name value)))
                                      `~value))
                                    (map constraints
                                      [:gridx :gridy :gridwidth :gridheight
                                       :weightx :weighty :anchor :fill
                                       :insets :ipadx :ipady]))]
                              `(.add ~component (new GridBagConstraints
                                                     ~@constraint-values)))))
                        ret)))))
              ret)))))
    

    Thanks to amalloy, user100464, and kotarak for the help.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

For some reason I can't get clojure REPL working with jline, what i did
I'm using Clojure, but I can read Java, so this isn't a Clojure specific
I'm trying to get into the Clojure community. I've been working a lot with
I'm trying to get clojure/emacs/swank/cake all working together. According to assembla I need 'cake
Am new to clojure and learning it by working through SICP. I cannot get
I'm working through the Clojure examples in Stuart Halloway's Programmming Clojure and I've hit
I have the following Clojure code and I'm not sure why it's not working:
I'm working on Clojure app where a client needs to send some commands to
I'm working on some Clojure code that has some circular dependencies between different namespaces
I'm working on an application in Clojure that needs to multiply large matrices and

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.