Java布局管理器垂直居中

16

我有一个使用群组布局来组织一些标签的面板。我希望在重新调整大小时仍然将此面板保持在屏幕中央。如果我将该面板放入另一个使用流式布局的面板中,我可以使标签在水平方向上保持居中,但垂直方向上则不能保持居中。哪种布局管理器可以让我将面板保持在屏幕中央?

我还尝试了边框布局并将其放置在中心位置,但它会随着窗口大小而调整大小。

4个回答

26

尝试使用GridBagLayout,并使用空的GridBagConstraints对象添加面板。
例如:

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setLayout(new GridBagLayout());
    JPanel panel = new JPanel();
    panel.add(new JLabel("This is a label"));
    panel.setBorder(new LineBorder(Color.BLACK)); // make it easy to see
    frame.add(panel, new GridBagConstraints());
    frame.setSize(400, 400);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}

3
我一直想知道如何做到这一点,最终我放弃了,改用MigLayout。 - gencoreoperative
当容器的大小小于子元素的首选大小(但大于最小大小)时,GridBagLayout会严重失败。 - Mark Jeronimus

12

首先,我应该提到,阅读我的布局文章:http://web.archive.org/web/20120420154931/http://java.sun.com/developer/onlineTraining/GUI/AWTLayoutMgr/。虽然它有些陈旧,但非常有帮助(不幸的是,该文章比BoxLayout还要早)。我在JavaOne上发表演讲时有一些幻灯片,其中包括BoxLayout,地址为http://javadude.com/articles/javaone

尝试使用BoxLayout:

Box verticalBox = Box.createVerticalBox();
verticalBox.add(Box.createVerticalGlue());
verticalBox.add(stuffToCenterVertically);
verticalBox.add(Box.createVerticalGlue());

如果你想让这些内容居中,可以使用一个水平框(HorizontalBox)作为要垂直居中的内容:

Box horizontalBox = Box.createHorizontalBox();
horizontalBox.add(Box.createHorizontalGlue());
horizontalBox.add(stuffToCenter);
horizontalBox.add(Box.createHorizontalGlue());

相比GridBag,这种方法在代码中更容易“看到”


2
我同意GridBagLayout通常更复杂,但是对于居中一个单独的面板来说,只需要两行代码。 - Michael Myers
问题在于阅读代码时你无法“看到”它... (我已经将我的答案编辑为“看到”而不是“更容易”...) - Scott Stanchfield
我“看到了”……但另一方面,“createVerticalGlue()”如果不读文档,对我也没有意义。 - Michael Myers
1
公平...但比空的GridBagConstraints多了一点提示;) - Scott Stanchfield
我同意使用BoxLayout会更加顺利。它们比GridBag容易得多。无论你选择什么,阅读一些文档(至少是Swing Layout示例文档,它非常简短)总是一个好主意。 - David Irwin
Rassafrassa Oracle... 我更新了链接,指向了Wayback Machine。我会在某个时候复制这篇文章。 - Scott Stanchfield

0

你可以构建自己的LayoutManager来将单个组件居中(在两个轴上或仅在一个轴上)。这是一个在两个轴上都能实现居中的示例,你可以轻松地将其更改为垂直或水平居中。

当前的实现方式首先布局可见的子元素,你也可以进行更改...

public class CentreLayout implements LayoutManager, java.io.Serializable {

public void addLayoutComponent(String name, Component comp) {
}

public void removeLayoutComponent(Component comp) {
}

public Dimension preferredLayoutSize(Container target) {
    return target.getPreferredSize();
}

public Dimension minimumLayoutSize(Container target) {
    return target.getMinimumSize();
}

public void layoutContainer(Container target) {
    synchronized (target.getTreeLock()) {
        Insets insets = target.getInsets();
        Dimension size = target.getSize();
        int w = size.width - (insets.left + insets.right);
        int h = size.height - (insets.top + insets.bottom);
        int count = target.getComponentCount();

        for (int i = 0; i < count; i++) {
            Component m = target.getComponent(i);
            if (m.isVisible()) {
                Dimension d = m.getPreferredSize();
                m.setBounds((w - d.width) / 2, (h - d.height) / 2, d.width, d.height);
                break;
            }
        }
    }
}

}

不幸的是,这对我不起作用。在方法preferredLayoutSize中,我遇到了堆栈溢出(哈哈)。 - Atmocreations

0

在面板本身上使用 GroupLayout.Alignment.CENTER 进行 垂直和水平居中,并使用 setPreferredSize(new Dimension(yourChosenWidth,yourChosenHeight)) 设置面板不可调整大小。

为了安全起见,您还可以在面板上设置 setMinimumSizesetMaximumSize

如果您感觉自己很棒,可以通过仔细选择并分组标签,只使用一个单一的 GroupLayout 来完成整个过程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接