I have a Swing program using SwingLayout. The structure of the Swing components looks like this.

JFrame
    JPanel (Cardlayout)
        JPanel (Miglayout) - Main panel
            Jpanel (Flowlayout) - Checkbox Panel
            JPanel (Flowlayout) - Option Panel

My problem right now is that I'm not sure how to prevent the checkbox panel from growing. I don't want it to "push" out the column that it's in to the right. I want Wraplayout (which works fine on the option panel) to wrap the content of the checkbox panel when it grows too big.

This is the view of it from the Windowsbuilder GUI inside of Eclipse. The panel with the label "sites" in it is the Checkbox Panel. Directly to the right of the Checkbox panel is the Option panel. The big panel containing both of them is the main panel. http://i.imgur.com/S7Njo.png

This is what happens when I add too many checkboxes http://i.imgur.com/f2SZz.png

My main problem is that I don't understand why setting "grow 0" on the column constraint for the first column in mainpanel doesn't prevent it from growing when the component inside gets too big as I add new checkboxes to the site panel (the site panel can have an arbitrary number of checkboxes).

This is my miglayout for the main panel.

mainPanel.setLayout(new MigLayout("", "[][grow]", "[][][][][][][][grow]"));

Here are my component constraints for when I add the checkbox panel

siteCheckBoxPanel = new JPanel();
mainPanel.add(siteCheckBoxPanel, "cell 0 0,alignx left,gapx 0px,aligny center");
siteCheckBoxPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

I've also tried it without flow layout, and that doesn't fix anything. Any insight you could provide would be great! I'm also happy to provide more information if people have questions. FYI I've also tried "grow 0" on both the column and row constraint for the cell that the Checkbox Panel is inside.

Here's an SSCCE. You can grab the source below. The only dependency you need is miglayout. You can click on the button to add checkboxes.

https://dl.dropbox.com/u/20614368/Test.java

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;

import net.miginfocom.swing.MigLayout;


public class Test extends JFrame {


    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            private Test frame;

            public void run() {
                try {
                    frame = new Test();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private JPanel contentPane;
    private JPanel mainPanel;
    private JPanel optionPanel;
    private JButton btnUploadImages;
    private JLabel thumbnailLabel;
    private JTextArea textArea;
    private JPanel checkboxPanel;
    private final Action action = new SwingAction();

    /**
     * Create the frame.
     */
    public Test() {
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 1098, 846);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new CardLayout(0, 0));

        mainPanel = new JPanel();
        mainPanel.setName("");
        contentPane.add(mainPanel, "name_329556913535654");
        mainPanel.setLayout(new MigLayout("", "[][grow]", "[][][][][][][][grow]"));


        JLabel lblPicture = new JLabel("Picture");
        mainPanel.add(lblPicture, "cell 0 1");

        optionPanel = new JPanel();
        optionPanel.setBackground(Color.red);
        mainPanel.add(optionPanel, "cell 1 0 1 5,grow");

        btnUploadImages = new JButton("Upload Images");
        btnUploadImages.setAction(action);

        thumbnailLabel = new JLabel("");
        mainPanel.add(thumbnailLabel, "cell 0 4");

        textArea = new JTextArea();
        mainPanel.add(btnUploadImages, "cell 0 6");

        checkboxPanel = new JPanel();
        checkboxPanel.setBackground(Color.green);
        mainPanel.add(checkboxPanel, "flowx,cell 0 0");

        JLabel lblSites = new JLabel("Sites");
        checkboxPanel.add(lblSites);


    }
    private class SwingAction extends AbstractAction {
        public SwingAction() {
            putValue(NAME, "Add checkbox");
            putValue(SHORT_DESCRIPTION, "Some short description");
        }
        public void actionPerformed(ActionEvent e) {
            JCheckBox box = new JCheckBox();
            box.setName("Foobar!");
            checkboxPanel.add(box);
            contentPane.validate();
            contentPane.repaint();
        }
    }
}
有帮助吗?

解决方案

Theoretically, your setup should work as you expect - provided you tell the layout

  • to not grow the first column beyond a max, f.i. by setting a max to a percentage
  • to not shrink the optionPanel column under its pref, f.i. by setting the min to pref in the column constraints

example column constraints:

// first column - restrict max  
"[grow, fill, n:pref:30%]" +
// second column - restrict min 
"[grow, pref:pref:n]" 

Practically, I couldn't make FlowLayout and MigLayout play nicely together by whatever constraints: even the initial layout is broken (f.i. the optionPanel pushed off the frame width). Replacing FlowLayout by Rob's WrapLayout looks nicer, though not entirely optimal as the boxes are not completely aligned below each other.

/*
 * Created on 12.09.2012
 *
 */
package layout;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;

import net.miginfocom.swing.MigLayout;

public class MigLayoutNested extends JFrame {


    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            private MigLayoutNested frame;

            public void run() {
                try {
                    frame = new MigLayoutNested();
                    frame.pack();
//                    frame.setSize(frame.getWidth(), frame.getHeight()* 2);
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private JPanel contentPane;
    private JPanel mainPanel;
    private JPanel optionPanel;
    private JButton btnUploadImages;
    private JLabel thumbnailLabel;
    private JTextArea textArea;
    private JPanel checkboxPanel;
    private final Action action = new SwingAction();

    /**
     * Create the frame.
     */
    public MigLayoutNested() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        contentPane = (JPanel) getContentPane(); //new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new CardLayout(0, 0));

        mainPanel = new JPanel();
        contentPane.add(mainPanel, "name_329556913535654");

        mainPanel.setLayout(new MigLayout("debug", 
                "[grow, fill][grow, pref:pref:n]" 
               , "[grow, fill][][][][][][][grow]"
                ));

        // stand-in to simulate a row-spanning all-growing component
        optionPanel = new JPanel();
        ((FlowLayout) optionPanel.getLayout()).setAlignment(JLabel.RIGHT);
        JLabel option = new JLabel("just some label so we see the trailing corner, long enough");
        optionPanel.add(option);
        optionPanel.setBackground(Color.YELLOW);
        mainPanel.add(optionPanel, "cell 1 0 1 5, grow");

        // the panel to dynamically add components to  
        // expected behaviour is to wrap on revalidate if needed
        // not working with FlowLayout, but looks half-way fine
        // with Rob's WrapLayout
        checkboxPanel = new JPanel(new WrapLayout()); 
        checkboxPanel.setBackground(Color.green);
        JLabel lblSites = new JLabel("Sites");
        checkboxPanel.add(lblSites);
        mainPanel.add(checkboxPanel, "cell 0 0");

        JLabel lblPicture = new JLabel("Picture");
        mainPanel.add(lblPicture, "cell 0 1");

        thumbnailLabel = new JLabel("thumb");
        mainPanel.add(thumbnailLabel, "cell 0 3");
        textArea = new JTextArea(10, 10);
        mainPanel.add(textArea, "cell 0 4");

        btnUploadImages = new JButton("Upload Images");
        btnUploadImages.setAction(action);
        mainPanel.add(btnUploadImages, "cell 0 6");


    }
    private class SwingAction extends AbstractAction {
        public SwingAction() {
            putValue(NAME, "Add checkbox");
            putValue(SHORT_DESCRIPTION, "Some short description");
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            JCheckBox box = new JCheckBox();
            box.setName("Foobar!");
            checkboxPanel.add(box);
            checkboxPanel.revalidate();
        }
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top