Ivo
Ivo

Reputation: 450

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.

Upvotes: 1

Views: 1698

Answers (2)

David Kroukamp
David Kroukamp

Reputation: 36423

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();
            }
        });
    }
}

Upvotes: 3

Amarnath
Amarnath

Reputation: 8865

I have use BorderLayout and FlowLayout to manage the layouts. The frame has two JPanel's and one JPanel in it has two more JPanel's. All the internal panels use FlowLayout to align the JLabels. To arrange these panels on the JFrame I have used BorderLayout.

Layout Manager

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

public class LayoutTest {

    public LayoutTest() {

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(new GridBagLayout());

        JPanel motherPanel = new JPanel(new BorderLayout());

        JPanel topPanel = new JPanel(new BorderLayout());
        JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

        motherPanel.add(topPanel, BorderLayout.NORTH);
        motherPanel.add(bottomPanel, BorderLayout.CENTER);

        JPanel topUpperPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JPanel topBottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

        topUpperPanel.setBorder(new LineBorder(Color.BLACK));
        topBottomPanel.setBorder(new LineBorder(Color.BLACK));
        bottomPanel.setBorder(new LineBorder(Color.BLACK));

        topPanel.add(topUpperPanel, BorderLayout.PAGE_START);
        topPanel.add(topBottomPanel, BorderLayout.CENTER);

        for(int i = 0; i < 3; i++) {
            JLabel label = new JLabel("Label-" + String.valueOf(i));
            label.setBorder(new LineBorder(Color.BLACK));
            topUpperPanel.add(label);
        }

        for(int i = 0; i < 2; i++) {
            JLabel label = new JLabel("Label-" + String.valueOf(i));
            label.setBorder(new LineBorder(Color.BLACK));
            topBottomPanel.add(label);
        }

        for(int i = 0; i < 5; i++) {
            JLabel label = new JLabel("Label-" + String.valueOf(i));
            label.setBorder(new LineBorder(Color.BLACK));
            bottomPanel.add(label);
        }

        frame.add(motherPanel);
        frame.setTitle("Layout Manager");
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new LayoutTest();
            }
        });
    }
}

P.S: I would suggest you to separate the panels such that there will be "whithout no interference with remaining JPanels."

Upvotes: 3

Related Questions