5

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

下面是一些代码(假设pane是JFrame的内容窗格,并且之前已经创建了按钮、progressBar和label):

BoxLayout layout = new BoxLayout(pane, BoxLayout.Y_AXIS);
pane.setLayout(layout);
button.setAlignmentX(Component.CENTER_ALIGNMENT);
pane.add(button);
progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
pane.add(progressBar);
label.setAlignmentX(Component.LEFT_ALIGNMENT);
pane.add(label);

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

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

4

5 回答 5

7

BoxLayout 无法处理不同的对齐方式:请参阅http://download.oracle.com/javase/tutorial/uiswing/layout/box.html

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

于 2011-04-18T13:37:05.530 回答
5

有时您需要有一点创意并使用嵌套面板。但我更喜欢这种方法,而不是尝试学习和记住在使用其他布局管理器(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);
    }
}
于 2011-04-18T15:55:35.320 回答
2

为了补充我对原始问题的评论,这里有一个使用DesignGridLayout的片段:

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

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

于 2011-04-18T13:32:51.270 回答
1

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

使用标准布局管理器手动编码摆动布局可能非常令人沮丧。为此,我使用MiG Layout 。它是直截了当的,您只需几行代码就拥有一个不错的布局。如果您没有被迫使用 BoxLayout,我建议您试一试。

于 2011-04-18T12:35:37.303 回答
1

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

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


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

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

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

(可选地,第一个参数指示对齐方式)。

于 2011-04-18T12:44:21.573 回答