Java 请帮助我了解BoxLayout对齐问题

Java 请帮助我了解BoxLayout对齐问题,java,swing,alignment,boxlayout,Java,Swing,Alignment,Boxlayout,我正在尝试使用Java布局创建一个非常简单的窗口。我有三个元素要安排:一个按钮、一个进度条和一个标签。按钮必须垂直居中,进度条必须全宽,标签必须左对齐 下面是一些代码(假设pane是JFrame的内容窗格,并且按钮、进度条和标签以前已经创建过): 当我测试应用程序时,我看到所有的东西都没有对齐和扭曲:按钮和标签是随机缩进的,如果我调整窗口的大小,缩进量会以一种奇怪的方式改变。 进度条看起来不错(全宽) 我只是不明白发生了什么。你能给我一个线索吗?也许你的代码只是一个片段,但我错过了对pack()

我正在尝试使用Java布局创建一个非常简单的窗口。我有三个元素要安排:一个按钮、一个进度条和一个标签。按钮必须垂直居中,进度条必须全宽,标签必须左对齐

下面是一些代码(假设pane是JFrame的内容窗格,并且按钮、进度条和标签以前已经创建过):

当我测试应用程序时,我看到所有的东西都没有对齐和扭曲:按钮和标签是随机缩进的,如果我调整窗口的大小,缩进量会以一种奇怪的方式改变。 进度条看起来不错(全宽)


我只是不明白发生了什么。你能给我一个线索吗?

也许你的代码只是一个片段,但我错过了对
pack()
的调用


手工编写swing布局对于标准布局管理器来说可能非常令人沮丧。我用它来做这个用途。这是直接的,你有一个很好的布局,只有几行代码。如果你不是被迫使用BoxLayout,我建议你试试。

不要使用BoxLayout。它只适用于非常简单的情况

对于您的情况,我推荐GridBagLayout或(我最喜欢的)GroupLayout


对于GroupLayout,我创建了一个子类(),其中包含一些实用方法和有用的构造函数,这使得编写布局更加容易

当然,通常我以相同的方式对齐一组中的所有组件,因此它不像在简单情况下那样短

    LayoutHelper h = new LayoutHelper(pane);

    h.setVerticalGroup
        ( h.sequential( button, progressBar, label));

    h.setHorizontalGroup
        ( ((ParallelGroup)h.parallel())
          .addComponent(button, Alignment.CENTER)
          .addComponent(progressBar)
          .addComponent(label, Alignment.TRAILING));
以下是一个屏幕截图:

对于一个简单的“所有东西都以相同的方式对齐”,水平组如下所示:

    h.setHorizontalGroup
        ( h.parallel (button, progressBar, label));

(可以选择使用第一个参数表示对齐)。

为了补充我对原始问题的评论,下面是一个使用以下内容的片段:


它完全符合您问题中的描述,不需要对任何组件进行任何特定调用。

BoxLayout无法处理不同的对齐方式:请参阅


引用那篇文章的话:“一般来说,由自上而下的BoxLayout对象控制的所有组件都应该具有相同的X对齐方式。类似地,由左到右的BoxLayout对象控制的所有组件通常都应该具有相同的Y对齐方式。”

有时,您需要有点创意,并使用嵌套面板。但我更喜欢这种方法,而不是尝试学习和记忆使用其他布局管理器(GridBagLayout、GroupLayout)时所需的所有约束条件,这些布局管理器设计用于为您生成代码的IDE

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

public class BoxLayoutVertical extends JFrame
{
    public BoxLayoutVertical()
    {
        Box box = Box.createVerticalBox();

        JButton button = new JButton("A button");
        button.setAlignmentX(Component.CENTER_ALIGNMENT);
        box.add(button);

        JProgressBar progressBar = new JProgressBar(0, 100);
        progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
        box.add(progressBar);

        JPanel panel = new JPanel( new BorderLayout() );
        JLabel label = new JLabel("A label");
        label.setAlignmentX(Component.LEFT_ALIGNMENT);
        panel.add(label);
        box.add(panel);

        add(box, BorderLayout.NORTH);
    }

    public static void main(String[] args)
    {
        BoxLayoutVertical frame = new BoxLayoutVertical();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.setSize(300, 200);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}

我喜欢这种MiG布局,但我真的不想为这样一个非常非常简单的应用程序链接其他JAR并将其推到更“复杂”的级别。@Giacomo:Fair够了;)“丢失的”pack()不是问题所在?就我个人而言,我从不信任setAlignmentX或setAlignmentY,并试图避免它们成为瘟疫,我也会避免完全依赖它们的布局管理器。我现在明白你为什么这么做了。。。你会建议什么替代方案呢?好吧,如果你必须坚持纯JDK,那么我可能会在你的案例中使用GridBagLayout;这将很好地工作,因为您的布局很简单(当您的布局有更多组件时,GBL开始变得复杂)。否则,我将使用DesignGridLayout。@Paulo您是否手工编写了GroupLayout?然后你似乎有太多的空闲时间:-)@kleopatra:我有一个包装器类,它有点方便。(我将添加它与此相关的外观)。一个简单的GroupLayout并不好,但也不比GridBagLayout好多少。@Giacomo:老实说,我不知道BoxLayout有什么好处。我在使用它时也遇到了一些问题,尤其是与布局方向正交的对齐方式。谢谢,所以BoxLayout对我来说是垃圾。我会按照你的提示去做。你确定它不能处理不同的对齐方式吗@安德鲁斯:当你建议长方体可以处理不同的对齐方式时,你指的是教程的哪一部分?解决方案是否涉及使用Box.createHorizontalGlue(),或者这是否可能?@Mins,请查看名为BoxLayoutDemo2的图像示例的部分。您将看到,使用Component.LEFT\u对齐、Component.CENTER\u对齐和Component.RIGHT\u对齐,组件之间是相对对齐的。@AndrewS:这对我不起作用,我已经发布了代码。出什么问题了?有史以来最好的解决方案,因为它不涉及额外的库,也不涉及额外的类,而且它是针对我所面临的问题定制的。然而,我将遵循其他用户的解决方案来了解更多关于布局的信息,但在本例中,我正在寻找一种简单的方法。
JButton button = new JButton("Button");
JProgressBar progressBar = new JProgressBar();
JLabel label = new JLabel("Label");

// The interesting stuff is in the next 4 lines
DesignGridLayout layout = new DesignGridLayout(getContentPane());
layout.row().center().add(button).withOwnRowWidth();
layout.row().center().fill().add(progressBar);
layout.row().left().add(label);

pack();
import java.awt.*;
import javax.swing.*;

public class BoxLayoutVertical extends JFrame
{
    public BoxLayoutVertical()
    {
        Box box = Box.createVerticalBox();

        JButton button = new JButton("A button");
        button.setAlignmentX(Component.CENTER_ALIGNMENT);
        box.add(button);

        JProgressBar progressBar = new JProgressBar(0, 100);
        progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
        box.add(progressBar);

        JPanel panel = new JPanel( new BorderLayout() );
        JLabel label = new JLabel("A label");
        label.setAlignmentX(Component.LEFT_ALIGNMENT);
        panel.add(label);
        box.add(panel);

        add(box, BorderLayout.NORTH);
    }

    public static void main(String[] args)
    {
        BoxLayoutVertical frame = new BoxLayoutVertical();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.setSize(300, 200);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}