如何使包含 FlowLayout 的 JPanel 居中?
How do I center a JPanel containing a FlowLayout?
我有一个包含一些组件的 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);
}
}
如果 window 的宽度足以让两个按钮并排放置,它几乎看起来居中:
但是如果它太小你可以清楚地看到我的问题:
问题是 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 的 JPanel 居中
setLayout(new FlowLayout(FlowLayout.CENTER));
The problem is that the JPanel takes the lower half of the JFrame and the Glue the upper half:
问题是 BoxLayout 将允许组件增长到组件的最大尺寸。在面板的情况下,最大尺寸是最大整数值,因此胶水和面板都获得相等数量的 space。因此,如果您想使用 BoxLayout,则需要重写 getMaximumSize()
方法以 return 面板的首选大小。
I tried to use a BoxLayout with a VerticalGlue, but it doesn't center it completely.
进行上述更改后,您需要使用 verticalGlue 两次:
Box box = new Box.createVerticalBox();
box.add( Box.createVerticalGlue() );
box.add( panel );
box.add( Box.createVerticalGlue() );
现在面板上方和下方的 space 数量相等。但是,当组件换行到下一行时,这仍然不起作用,因为 FlowLayout
不会根据换行的组件重新计算高度。因此,在这种情况下,您可以将 FlowLayout
替换为 Wrap Layout,它只是扩展 FlowLayout
以正确计算包裹高度。
或者不使用 BoxLayout,您可以使用 GridBagLayout。默认情况下,添加到 GridBagLayout 的组件将水平和垂直居中。您仍然需要带有 WrapLayout
的面板
这里是一个使用 WrapLayout mentioned by 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);
}
}
我有一个包含一些组件的 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);
}
}
如果 window 的宽度足以让两个按钮并排放置,它几乎看起来居中:
但是如果它太小你可以清楚地看到我的问题:
问题是 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 的 JPanel 居中
setLayout(new FlowLayout(FlowLayout.CENTER));
The problem is that the JPanel takes the lower half of the JFrame and the Glue the upper half:
问题是 BoxLayout 将允许组件增长到组件的最大尺寸。在面板的情况下,最大尺寸是最大整数值,因此胶水和面板都获得相等数量的 space。因此,如果您想使用 BoxLayout,则需要重写 getMaximumSize()
方法以 return 面板的首选大小。
I tried to use a BoxLayout with a VerticalGlue, but it doesn't center it completely.
进行上述更改后,您需要使用 verticalGlue 两次:
Box box = new Box.createVerticalBox();
box.add( Box.createVerticalGlue() );
box.add( panel );
box.add( Box.createVerticalGlue() );
现在面板上方和下方的 space 数量相等。但是,当组件换行到下一行时,这仍然不起作用,因为 FlowLayout
不会根据换行的组件重新计算高度。因此,在这种情况下,您可以将 FlowLayout
替换为 Wrap Layout,它只是扩展 FlowLayout
以正确计算包裹高度。
或者不使用 BoxLayout,您可以使用 GridBagLayout。默认情况下,添加到 GridBagLayout 的组件将水平和垂直居中。您仍然需要带有 WrapLayout
这里是一个使用 WrapLayout mentioned by 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);
}
}