【问题标题】:How do I center a JPanel containing a FlowLayout?如何将包含 FlowLayout 的 JPanel 居中?
【发布时间】:2015-08-26 01:11:30
【问题描述】:

我有一个 JPanel,其中包含一些组件,并使用 FlowLayout 将它们布置好,以便在必要时将它们包装起来,并且我想将这个 JPanel 放在 JFrame 中。 我尝试将 BoxLayout 与 VerticalGlue 一起使用,但它并没有完全居中。 这是一个简单的 SSCCE,它演示了我的问题,因为我认为我不能很好地解释它:

import javax.swing.*;
public class Test extends JFrame {
    public static void main(String[] args) {
        new Test();
    }
    public Test() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
        getContentPane().add(Box.createVerticalGlue());
        JPanel panel = new JPanel();
        panel.add(new JButton("New button"));
        panel.add(new JButton("New button"));
        getContentPane().add(panel);
        setVisible(true);
    }
}

如果窗口的宽度足以让两个按钮彼此相邻,则它几乎看起来居中:

但如果它太小你可以清楚地看到我的问题:

问题是 JPanel 占据了 JFrame 的下半部分,而 Glue 占据了上半部分:

我也尝试过其他的 LayoutManager,但我还不能解决这个问题。

编辑:

BorderLayout 和 JPanel 位于中心,按钮显示在顶部,因为 JPanel 扩展为 JFrame 的 ContentPane 的大小:

使用 GridBagLayout,它看起来很完美,所有东西都彼此相邻。但如果组件被包裹起来,它们就会消失:

使用 MigLayout,按钮将不再换行:

编辑: 我使用的解决方案是Wrap Layout 与 GridBagLayout 的组合:

import java.awt.*;
import javax.swing.*;
class Test extends JFrame {
    public static void main(String[] args) {
        new Test();
    }
    Test() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWeights = new double[]{1.0};
        getContentPane().setLayout(gridBagLayout);
        JPanel panel = new JPanel(new WrapLayout());
        GridBagConstraints gbc_panel = new GridBagConstraints();
        gbc_panel.fill = GridBagConstraints.HORIZONTAL;
        getContentPane().add(panel, gbc_panel);
        panel.add(new JButton("New button"));
        panel.add(new JButton("New button"));
        setVisible(true);
    }
}

【问题讨论】:

  • 我会尝试将 FlowLayout 嵌套在 BorderLayout 的中心...
  • 如果这些是面板上唯一的组件,并且您想准确了解它们的位置,我建议使用 NullLayout (setLayout(null)) 并使用 setBounds()。 docs.oracle.com/javase/tutorial/uiswing/layout/none.html为了解决你的大小调整问题,只需让setBounds()方法的参数与JFrame的大小成比例即可。
  • @javaislife I would suggest using NullLayout (setLayout(null)) and utilizing setBounds().:最糟糕的建议。永远不要使用空布局!只需使用 gridbaglayout 将面板包装到周围的面板中,默认约束将执行 OP 想要的操作
  • 我会为此使用MigLayout,对于任何其他情况。

标签: java swing jpanel layout-manager


【解决方案1】:

您可以通过此代码将包含 FlowLayout 的 JPanel 居中

setLayout(new FlowLayout(FlowLayout.CENTER));

【讨论】:

  • 这只会水平居中 JPanel 而不是垂直居中。我希望 JPanel 在两个方向上居中。
【解决方案2】:

问题是 JPanel 占用了 JFrame 的下半部分,而 Glue 占用了上半部分:

问题在于 BoxLayout 将允许组件增长到组件的最大尺寸。在面板的情况下,最大尺寸是最大整数值,因此胶水和面板都获得相等的空间。所以如果你想使用 BoxLayout,你需要重写getMaximumSize() 方法来返回面板的首选大小。

我尝试将 BoxLayout 与 VerticalGlue 一起使用,但它并没有完全居中。

经过上述修改后,您需要使用两次verticalGlue:

Box box = new Box.createVerticalBox(); 
box.add( Box.createVerticalGlue() );
box.add( panel );
box.add( Box.createVerticalGlue() );

现在您将在面板上方和下方拥有相等的空间。但是,当组件包裹到下一行时,这仍然不起作用,因为FlowLayout 不会根据包裹的组件重新计算高度。因此,在这种情况下,您可以将 FlowLayout 替换为 Wrap Layout,它只是扩展 FlowLayout 以正确计算包裹高度。

或者,您可以使用 GridBagLayout,而不是使用 BoxLayout。默认情况下,添加到 GridBagLayout 的组件将水平和垂直居中。您仍然需要带有 WrapLayout 的面板

【讨论】:

  • 我使用的解决方案是您推荐的 Wrap Layout 与 GridBagLayout 的组合。
【解决方案3】:

这是使用camickr 提到的WrapLayout 的示例。我不得不弄乱包装面板的最大尺寸,这有点麻烦,但我认为这足以让你指出正确的方向。

public class Test extends JFrame {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setLayout(new BorderLayout());

        JPanel boxPanel = new JPanel();
        boxPanel.setLayout(new BoxLayout(boxPanel, BoxLayout.Y_AXIS));
        boxPanel.setBorder(BorderFactory.createLineBorder(Color.GREEN, 1));

        JPanel wrapPanel = new JPanel();

        // hack of panel max size
        wrapPanel.setMaximumSize(new Dimension(99999, 0));
        wrapPanel.setBorder(BorderFactory.createLineBorder(Color.RED, 1));
        wrapPanel.setLayout(new WrapLayout(FlowLayout.CENTER));
        wrapPanel.add(new JButton("New button"));
        wrapPanel.add(new JButton("New button"));

        boxPanel.add(Box.createGlue());     
        boxPanel.add(wrapPanel);
        boxPanel.add(Box.createGlue());     

        add(boxPanel, BorderLayout.CENTER);

        setVisible(true);
    }
}

【讨论】:

    猜你喜欢
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    相关资源
    最近更新 更多