Java Swing远离空布局

Java Swing远离空布局,java,swing,layout-manager,null-layout-manager,Java,Swing,Layout Manager,Null Layout Manager,我使用不赞成的空布局构建了一个很棒的GUI(我定义了很多常量,并使用了一个窗口调整侦听器来简化)。在我开始使用新电脑之前,一切都很顺利。现在,组件的位置不正确(从图片中可以看到组件向下和向右偏移)。在研究了这个问题之后,我了解到布局管理器确保组件在不同的机器中正确定位。因此,我想开始在实际的布局管理器中重建GUI。问题是,当我试图使用实际的布局管理器时,我经常觉得我定位组件的方式有限 对于任何好奇的人来说,我最初使用的是带有windows 10的dell inspiron笔记本电脑,现在已经换成

我使用不赞成的空布局构建了一个很棒的GUI(我定义了很多常量,并使用了一个窗口调整侦听器来简化)。在我开始使用新电脑之前,一切都很顺利。现在,组件的位置不正确(从图片中可以看到组件向下和向右偏移)。在研究了这个问题之后,我了解到布局管理器确保组件在不同的机器中正确定位。因此,我想开始在实际的布局管理器中重建GUI。问题是,当我试图使用实际的布局管理器时,我经常觉得我定位组件的方式有限

对于任何好奇的人来说,我最初使用的是带有windows 10的dell inspiron笔记本电脑,现在已经换成了同样带有windows 10的华硕笔记本电脑(我不知道实际型号,但触摸屏可以与键盘分离)

我的问题:

哪个布局管理器最快、最容易构建上图所示的GUI(现成的Swing布局和其他布局)。我希望此布局只考虑少数但不是所有组件的实际尺寸。使用此布局,我将如何定位库存按钮(左下角的锤子),以便库存按钮的左下角距离容器的左下角向上和向右5像素,即使在调整容器大小后也是如此

提前谢谢。感谢所有的帮助


编辑:“找到钥匙”和“试图强行开门”选项的大小应该得到尊重。

我想到的最简单的解决方案是主面板的a。将
textarea
添加到
NORTH
/
页面_START
。制作另一个
BorderLayout
,其中包含库存按钮(
WEST
/
LINE\u START
)和位置标签(
EAST
/
LINE\u END
)。将其添加到主
边界布局的
页面的
南部
/
末尾
。然后只需在包含两个按钮的主
BorderLayout
CENTER
中添加一个垂直对齐。用于标准布局管理器



我想到的最简单的解决方案是为主面板设计一个。将
textarea
添加到
NORTH
/
页面_START
。制作另一个
BorderLayout
,其中包含库存按钮(
WEST
/
LINE\u START
)和位置标签(
EAST
/
LINE\u END
)。将其添加到主
边界布局的
页面的
南部
/
末尾
。然后只需在包含两个按钮的主
BorderLayout
CENTER
中添加一个垂直对齐。用于标准布局管理器



应遵守哪些部件的首选尺寸?我想到的最简单的解决方案是主面板的
BorderLayout
。将文本区域添加到
NORTH
。制作另一个包含库存按钮(
WEST
)和位置标签(
EAST
)的
BorderLayout
)。将其添加到主
BorderLayout
SOUTH
。然后只需将一个垂直对齐的
BoxLayout
添加到包含两个文本字段的主
BorderLayout
CENTER
。标准布局管理器中的一种。只有
GridBagLayout
GroupLayout
这两种布局具有足够的通用性,可以完成一个完整的UI。后者通常用于IDE中的GUI构建器。除了这两个,我通常会结合布局,为UI的每个部分使用最佳布局。对于底部部分,我将使用带有
边框布局的单个面板
,并将图标添加到
行开始
,将标签添加到
行结束
。要获得5px缩进,请使用底部面板上的
EmptyBorder
。不要指望它,也不要把鸡蛋放在一个篮子里——吠叫的狗会在这里吠叫,但几年后你会回来“哦,我的windows 11不运行这个东西!”哪个组件的首选尺寸应该得到尊重?我想到的最简单的解决方案是主面板的
BorderLayout
。将文本区域添加到
NORTH
。制作另一个包含库存按钮(
WEST
)和位置标签(
EAST
)的
BorderLayout
)。将其添加到主
BorderLayout
SOUTH
。然后只需将一个垂直对齐的
BoxLayout
添加到包含两个文本字段的主
BorderLayout
CENTER
。标准布局管理器中的一种。只有
GridBagLayout
GroupLayout
这两种布局具有足够的通用性,可以完成一个完整的UI。后者通常用于IDE中的GUI构建器。除了这两个,我通常会结合布局,为UI的每个部分使用最佳布局。对于底部部分,我将使用带有
边框布局的单个面板
,并将图标添加到
行开始
,将标签添加到
行结束
。要获得5px缩进,使用底部面板上的
EmptyBorder
。不要指望它,也不要把鸡蛋放在一个篮子里——吠叫的狗会在这里到处吠叫,但几年后你会回来“哦,我的windows 11没有运行这个东西!”你的例子很好,但是我不知道如何让布局尊重“查找钥匙”和“尝试强制开门”按钮的大小。我试图设置这些组件的最大、最小和首选大小,但运气不佳。@olta8通常不建议设置太多组件的首选大小。我在示例中也犯了一个错误:您应该调用类似
textArea.setRows(5)的内容;
而不是覆盖它的首选大小。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class Example {

    public Example() {
        JTextArea textArea = new JTextArea("There is a locked door");
        textArea.setRows(5);
        textArea.setBorder(BorderFactory.createLineBorder(Color.GRAY));
        textArea.setEditable(false);

        WhiteButton button1 = new WhiteButton("Go find a key") {
            @Override
            public Dimension getMinimumSize() {
                return new Dimension(200, 25);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 25);
            }

            @Override
            public Dimension getMaximumSize() {
                return new Dimension(200, 25);
            }
        };
        WhiteButton button2 = new WhiteButton("Attempt to force the door open");
        button2.setMargin(new Insets(0, 60, 0, 60));

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
        buttonPanel.add(button1);
        buttonPanel.add(Box.createVerticalStrut(5));
        buttonPanel.add(button2);

        WhiteButton inventoryButton = new WhiteButton(
                new ImageIcon(new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB)));

        JLabel locationLabel = new JLabel("Location: 0");
        locationLabel.setVerticalAlignment(JLabel.BOTTOM);

        JPanel southPanel = new JPanel(new BorderLayout());
        southPanel.add(inventoryButton, BorderLayout.WEST);
        southPanel.add(locationLabel, BorderLayout.EAST);

        JPanel mainPanel = new JPanel(new BorderLayout(0, 5));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        mainPanel.add(textArea, BorderLayout.NORTH);
        mainPanel.add(buttonPanel);
        mainPanel.add(southPanel, BorderLayout.SOUTH);

        JFrame frame = new JFrame("Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

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

    private class WhiteButton extends JButton {

        public WhiteButton() {
            setBackground(Color.WHITE);
        }

        public WhiteButton(String text) {
            this();
            setText(text);
        }

        public WhiteButton(ImageIcon icon) {
            this();
            setIcon(icon);
            setBorder(BorderFactory.createLineBorder(Color.GRAY));
        }

    }

}