javaswingjpanellayout-managermiglayout

How to resize a JPanel to fit a JFrame in "docknorth" with no interference to remaining JPanels


I am doing a little test of a demo Swing GUI. In this demo, the JFrame is composed of 3 "master" JPanels. If you will, the first (jp1) is composed of JLabels, and the other two are composed of several other JPanels. I am using MigLayout.

Here is my sample code:

    // All the jPanels  
    JFrame frame = new JFrame();
    frame.setLayout(new MigLayout());
    JPanel jp1 = new JPanel();
    jp1.setLayout(new MigLayout());
    jp1.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
    JPanel jp2 = new JPanel();
    jp2.setLayout(new MigLayout());
    jp2.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
    JPanel jp3 = new JPanel();
    jp3.setLayout(new MigLayout());
    jp3.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
    JPanel jp4 = new JPanel();
    jp4.setLayout(new MigLayout());
    jp4.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
    JPanel jp5 = new JPanel();
    jp5.setLayout(new MigLayout());
    jp5.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
    JPanel jp6 = new JPanel();
    jp6.setLayout(new MigLayout());
    jp6.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
    JPanel jp7 = new JPanel();
    jp7.setLayout(new MigLayout());
    jp7.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));

    JPanel bigPanel1 = new JPanel();
    bigPanel1.setLayout(new MigLayout());
    bigPanel1.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));

    JPanel bigPanel2 = new JPanel();
    bigPanel2.setLayout(new MigLayout());
    bigPanel2.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
    //All the labels to be added to JPanel jp1
    JLabel label1 = new JLabel();
    label1.setText("LABEL1");
    JLabel label2 = new JLabel();
    label2.setText("LABEL2");
    JLabel label3 = new JLabel();
    label3.setText("LABEL3");
    JLabel label4 = new JLabel();
    label4.setText("LABEL4");
    jp1.add(label1);
    jp1.add(label2);
    jp1.add(label3);
    jp1.add(label4,"wrap");
    bigPanel1.add(jp2);
    bigPanel1.add(jp6);
    bigPanel1.add(jp3,"grow,wrap");
    bigPanel2.add(jp4);
    bigPanel2.add(jp7);
    bigPanel2.add(jp5,"grow,wrap");
    frame.getContentPane().add(jp1,"dock north, wrap");
    frame.getContentPane().add(bigPanel1,"span,grow,wrap");
    frame.getContentPane().add(bigPanel2,"span,grow,wrap");
    frame.pack();
    frame.setVisible(true);

Which results in this output:GUI OUTPUT

What I want to achieve is being able to add labels into the 1st JPanel (jp1) without messing with the remainder JPanels width. Additionally, I want to make the several JPanels inside a bigPanel to occupy its full width, as well as in jp2,jp6 and jp3 to fill bigPanel1.

How should I do this? Thanks in advance.


Solution

  • I have never used MigLayout, and personally dont see the reason if it can be done using default java LayoutManager.

    Okay so I used a combination FlowLayout and GridBagLayout to achieve this, along with gc.fill=GridBagConstraints.NONE and gc.anchor=GridBagConstraints.WEST for those panels which we dont want to fill the contentpane width, also updated as per your comment to stop the JPanel/JFrame from growing larger than the given max width when more JLabels are added this was done using a JScrollPane:

    enter image description here

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.SwingUtilities;
    import javax.swing.border.LineBorder;
    
    public class Test {
    
        public Test() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.setLayout(new GridBagLayout());
    
            final JPanel labelPanel = new JPanel();
            labelPanel.setBorder(new LineBorder(Color.black));
            for (int i = 0; i < 5; i++) {
                labelPanel.add(new JLabel("Label" + (i + 1)));
            }
    
            final int maxWidth = 200;
            final JScrollPane jsp = new JScrollPane(labelPanel) {
                @Override
                public Dimension getPreferredSize() {
                    //we set the height by checking if we exceeed the wanted ith thus a scrollbar will appear an we must incoprate that or labels wont be shpwn nicely
                    return new Dimension(maxWidth, labelPanel.getPreferredSize().width < maxWidth ? (labelPanel.getPreferredSize().height + 5) : ((labelPanel.getPreferredSize().height + getHorizontalScrollBar().getPreferredSize().height) + 5));
                }
            };
    
            JPanel otherPanel = new JPanel();
            otherPanel.add(new JLabel("label"));
            otherPanel.setBorder(new LineBorder(Color.black));
    
            JPanel otherPanel2 = new JPanel();
            otherPanel2.add(new JLabel("label 1"));
            otherPanel2.add(new JLabel("label 2"));
            otherPanel2.setBorder(new LineBorder(Color.black));
    
            GridBagConstraints gc = new GridBagConstraints();
    
            gc.fill = GridBagConstraints.BOTH;
            gc.weightx = 1.0;
            gc.weighty = 1.0;
            gc.gridx = 0;
            gc.gridy = 0;
            frame.add(jsp, gc);
    
            gc.fill = GridBagConstraints.NONE;
            gc.anchor = GridBagConstraints.WEST;
            gc.gridy = 1;
            frame.add(otherPanel, gc);
            gc.anchor = GridBagConstraints.WEST;
            gc.gridy = 2;
            frame.add(otherPanel2, gc);
    
            frame.pack();
            frame.setVisible(true);
            frame.revalidate();
            frame.repaint();
        }
    
        public static void main(String[] args) {
            //Create Swing components on EDT
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Test();
                }
            });
        }
    }