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

≯℡__Kan透↙ 提交于 2019-12-24 07:58:04

问题


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.


回答1:


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:

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



回答2:


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.

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."



来源:https://stackoverflow.com/questions/14610153/how-to-resize-a-jpanel-to-fit-a-jframe-in-docknorth-with-no-interference-to-re

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!