调整多个 JPanel 的大小以适应窗口

问题描述

我是 Java Swing 工具包的新手,并创建了一系列 JPanel,其中 JLabel 组件对应于每个面板的索引和值。但是,当窗口太小而无法一次调整所有面板的大小时,我似乎无法正确调整面板的大小。导致所有面板右侧有一个额外的红色边距(参见。Window)。

有没有办法让子面板/间隔面板以不允许额外边距的方式调整大小?或者设置一个更好的摆动布局来处理这种调整大小?

代码演示:

import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import javax.swing.BoxLayout;

public class Frame extends JFrame {
    private int numBox = 20;

    public class SubPanel extends JPanel {
        public SubPanel(int i) {
            setMinimumSize(new Dimension(20,20));
            setMaximumSize(new Dimension(1000,i*30));
            setBackground(Color.BLACK);
            setLayout(new BorderLayout());
            setAlignmentY(Component.BottOM_ALIGNMENT);

            JLabel labelValue = new JLabel(String.valueOf(30 * i),JLabel.CENTER);
            labelValue.setForeground(Color.WHITE);
            add(labelValue,BorderLayout.norTH);

            JLabel labelIndex = new JLabel(String.valueOf(i),JLabel.CENTER);
            labelIndex.setForeground(Color.WHITE);
            add(labelIndex,BorderLayout.soUTH);
        }
    }

    public class SpacerPanel extends JPanel {
        public SpacerPanel() {
            setBackground(Color.WHITE);
            setMaximumSize(new Dimension(3,10000));
            setMinimumSize(new Dimension(3,0));
        }
    }

    public Frame(String title) {
        super(title);

        JPanel mainPanel = new JPanel();
        mainPanel.setBackground(Color.RED);
        mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.LINE_AXIS));

        for (int i = 1; i < numBox + 1; i++) {
            mainPanel.add(new SpacerPanel());
            mainPanel.add(new SubPanel(i));
        }
        mainPanel.add(new SpacerPanel());

        add(mainPanel);
        setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Frame("Frame").setSize(1200,700);
    }
}

解决方法

如果您有 40 个组件并且将框架的大小调整了几个像素,则 BoxLayout 在将这些像素分配给每个组件时会遇到问题。

相反,您可以使用 Relative Layout 来指定这些像素的分配方式。

RelativeLayout 还允许您指定每个组件之间的间隙,因此您无需添加 SpacerPanel。

但是,您需要修改“subPanel”的逻辑。标签的高度需要固定,以便将它们涂成黑色。所以我创建了一个“labelPanel”来保存标签。

使用 RelativeLayout 重构的代码将是:

import java.awt.*;
import javax.swing.*;
import javax.swing.JLabel;
import javax.swing.JPanel;

import javax.swing.BoxLayout;

public class Frame extends JFrame {
    private int numBox = 20;

    public class SubPanel extends JPanel {
        public SubPanel(int i) {
//            setMinimumSize(new Dimension(20,20));
//            setMaximumSize(new Dimension(1000,i*30));
//            setPreferredSize(new Dimension(20,i*30));
            setBackground(Color.RED);
            setLayout(new BorderLayout());
//            setAlignmentY(Component.BOTTOM_ALIGNMENT);

            JPanel labelPanel = new JPanel( new BorderLayout() );
            labelPanel.setBackground( Color.BLACK );
            labelPanel.setPreferredSize(new Dimension(20,i*30));
            add(labelPanel,BorderLayout.PAGE_END);

            JLabel labelValue = new JLabel(String.valueOf(30 * i),JLabel.CENTER);
            labelValue.setForeground(Color.WHITE);
            labelPanel.add(labelValue,BorderLayout.NORTH);

            JLabel labelIndex = new JLabel(String.valueOf(i),JLabel.CENTER);
            labelIndex.setForeground(Color.WHITE);
            labelPanel.add(labelIndex,BorderLayout.SOUTH);
        }
    }

    public class SpacerPanel extends JPanel {
        public SpacerPanel() {
            setBackground(Color.WHITE);
            setMaximumSize(new Dimension(3,10000));
            setMinimumSize(new Dimension(3,0));
        }
    }

    public Frame(String title) {
        super(title);

        JPanel mainPanel = new JPanel();
//        mainPanel.setBackground(Color.RED);
        mainPanel.setBackground(Color.WHITE);

//        mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.LINE_AXIS));
        RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS,5);
        rl.setFill( true );
        rl.setRoundingPolicy(RelativeLayout.EQUAL);
        rl.setAlignment(RelativeLayout.TRAILING);
        mainPanel.setLayout( rl );
        Float constraint = new Float(1);

        for (int i = 1; i < numBox + 1; i++) {
//            mainPanel.add(new SpacerPanel());
//            mainPanel.add(new SubPanel(i));
            mainPanel.add(new SubPanel(i),constraint);
        }
//        mainPanel.add(new SpacerPanel());

        add(mainPanel);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Frame("Frame").setSize(1200,700);
    }
}

或者这种方法更接近您的原始帖子。它仍然使用间隔器,随着框架高度的降低,黑柱的高度会缩小:

import java.awt.*;
import javax.swing.*;
import javax.swing.JLabel;
import javax.swing.JPanel;

import javax.swing.BoxLayout;

public class Frame2 extends JFrame {
    private int numBox = 20;

    public class SubPanel extends JPanel {
        public SubPanel(int i) {
//            setMinimumSize(new Dimension(20,i*30));
//            setBackground(Color.BLACK);
            setBackground(Color.RED);
//            setLayout(new BorderLayout());
            setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
            add(Box.createVerticalGlue());
//            setAlignmentY(Component.BOTTOM_ALIGNMENT);

            JPanel labelPanel = new JPanel();
            labelPanel.setLayout(new BoxLayout(labelPanel,BoxLayout.Y_AXIS));
            labelPanel.setBackground( Color.BLACK );
            labelPanel.setPreferredSize(new Dimension(50,i*30));
            labelPanel.setMaximumSize(new Dimension(1000,labelPanel.getPreferredSize().height));
            add(labelPanel,BorderLayout.CENTER);

            JLabel labelValue = new JLabel(String.valueOf(30 * i),JLabel.CENTER);
            labelValue.setForeground(Color.WHITE);
            labelValue.setAlignmentX(JLabel.CENTER_ALIGNMENT);
//            add(labelValue,BorderLayout.NORTH);
            labelPanel.add(labelValue);

            labelPanel.add(Box.createVerticalGlue());

            JLabel labelIndex = new JLabel(String.valueOf(i),JLabel.CENTER);
            labelIndex.setForeground(Color.WHITE);
            labelIndex.setAlignmentX(JLabel.CENTER_ALIGNMENT);
//            add(labelIndex,BorderLayout.SOUTH);
            labelPanel.add(labelIndex);
        }
    }

    public class SpacerPanel extends JPanel {
        public SpacerPanel() {
            setBackground(Color.WHITE);
            setMaximumSize(new Dimension(3,0));
        }
    }

    public Frame2(String title) {
        super(title);

        JPanel mainPanel = new JPanel();
        mainPanel.setBackground(Color.RED);
//        mainPanel.setLayout(new BoxLayout(mainPanel,0);
        rl.setFill( true );
        rl.setRoundingPolicy(RelativeLayout.EQUAL);
        rl.setAlignment(RelativeLayout.TRAILING);
        mainPanel.setLayout( rl );
        Float constraint = new Float(1);

        for (int i = 1; i < numBox + 1; i++) {
            mainPanel.add(new SpacerPanel());
//            mainPanel.add(new SubPanel(i));
            mainPanel.add(new SubPanel(i),constraint);
        }
        mainPanel.add(new SpacerPanel());

        add(mainPanel);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Frame2("Frame").setSize(1200,700);
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...