如何将包含FlowLayout的JPanel居中?

时间:2015-06-10 16:29:57

标签: java swing jpanel layout-manager

我有一个JPanel,其中包含一些组件,使用FlowLayout进行布局,以便在必要时将它们换行,并且我希望将此JPanel置于JFrame中。 我尝试使用带有VerticalGlue的BoxLayout,但它并没有完全居中。 这是一个简单的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占据了上半部分:

我也尝试过其他的LayoutManagers,但我还没有解决这个问题。

编辑:

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

3 个答案:

答案 0 :(得分:4)

  

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

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

  

我尝试使用带有VerticalGlue的BoxLayout,但它并没有完全居中。

完成上述更改后,您需要使用verticalGlue两次:

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

现在,您将在面板上方和下方拥有相同数量的空间。但是,当组件换行到下一行时,这仍然无法工作,因为FlowLayout不会根据包装的组件重新计算高度。因此,在这种情况下,您可以将FlowLayout替换为仅FlowLayout扩展WrapLayout的{​​{1}}来正确计算包裹高度。

或者不使用BoxLayout,您可以使用GridBagLayout。默认情况下,添加到GridBagLayout的组件将水平和垂直居中。您仍然需要具有<webview>

的面板

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

setLayout(new FlowLayout(FlowLayout.CENTER));