GridLayout
制作 2 x 2 网格,每个网格包含一个 JPanel
。
GridLayout
工作得很好,我只是做了mainPanel.setLayout(new GridLayout(2, 2))
,一切都很顺利。
但是,我注意到我的两个组件在网格内部(水平方向)有点狭窄。我知道我可以将布局交换为使用
CardLayout
或其他东西,但我正在构建的应用程序更像是一个仪表板,因此,同时查看所有元素是相当重要的。水平空间的缺乏是为了最大化窗口,所以最大化不是一个选择。
好吧,事实证明,其他 2 个组件有多余的水平空间,所以我心想,“为什么我不将 2 个大组件移到同一列,将 2 个小组件移到另一列,然后调整列的大小,以便它们都有所需的足够空间?”
这是我的意思的简单视觉表示。
事实证明,
GridLayout
(可以理解)不提供此功能,因此我决定循环浏览本教程中列出的不同 Swing 布局。在所有布局中,GridBagLayout 似乎最适合我的需求。
所以,我看了一下GridBagLayout
GridLayout
,然后操纵该解决方案,直到它看起来像我需要的。
这是我的第一次天真的尝试。这是浏览完教程后的结果。
import java.awt.*;
import javax.swing.*;
public class GUI
{
private final JFrame frame = new JFrame();
public GUI()
{
this.frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.frame.add(createPanel());
this.frame.setVisible(true);
}
private static JPanel createPanel()
{
final JPanel grid = new JPanel();
grid.setBorder(BorderFactory.createLineBorder(Color.MAGENTA));
final java.util.function.Supplier<JPanel> createButtonGrid =
() ->
{
final JPanel buttonGrid = new JPanel(new java.awt.GridLayout(4, 4));
for (int i = 0; i < 16; i++)
{
buttonGrid
.add
(
new
JButton
(
"""
<html>
THIS IS BUTTON TEXT<br>
THIS IS BUTTON TEXT<br>
THIS IS BUTTON TEXT<br>
THIS IS BUTTON TEXT
</html>
"""
)
);
}
return buttonGrid;
};
TOP_LEFT:
{
final GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
final JPanel tempPanel = createButtonGrid.get();
tempPanel.setBorder(BorderFactory.createLineBorder(Color.RED));
grid.add(tempPanel, c);
}
TOP_RIGHT:
{
final GridBagConstraints c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 0;
final JPanel tempPanel = createButtonGrid.get();
tempPanel.setBorder(BorderFactory.createLineBorder(Color.ORANGE));
grid.add(tempPanel, c);
}
BOTTOM_LEFT:
{
final GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 1;
final JPanel tempPanel = createButtonGrid.get();
tempPanel.setBorder(BorderFactory.createLineBorder(Color.GREEN));
grid.add(tempPanel, c);
}
BOTTOM_RIGHT:
{
final GridBagConstraints c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 1;
final JPanel tempPanel = createButtonGrid.get();
tempPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
grid.add(tempPanel, c);
}
return grid;
}
}
当我运行这个时,事情已经与预期有点不同了。所有组件都在中间被挤压。
GridLayout
确保每个组件占据所有可用的垂直和水平空间。如果我要使用GridBagLayout
,我需要这个。毕竟,我切换到 GridBagLayout
的全部原因是为了能够挤出更多一点水平宽度。我现在所拥有的只是倒退了一步。
所以,我再次仔细阅读了教程,这次彻底地阅读了以下引用。
填充
当组件的显示区域大于组件请求的大小时使用,以确定是否以及如何调整组件的大小。有效值(定义为 GridBagConstraints 常量)包括 NONE(默认值)、HORIZONTAL(使组件足够宽以水平填充其显示区域,但不更改其高度)、VERTICAL(使组件足够高以垂直填充其显示区域) ,但不改变其宽度),以及 BOTH(使组件完全填满其显示区域).
读到这里,我尝试为每个组件添加一个
c.fill = GridBagConstraints.BOTH;
。然而,结果是100%相同的。第一个版本和第二个版本没有区别。
第二次阅读时,我注意到以下引用。
GridBagLayout 将组件放置在行和列的网格中,允许指定的组件跨越多行或多列。并非所有行都必须具有相同的高度。同样,并非所有列都必须具有相同的宽度。本质上,GridBagLayout 将组件放置在网格中的矩形(单元格)中,然后 然后使用组件的首选大小来确定单元格应该有多大。
读到这里,我开始尝试不同的首选尺寸。这确实产生了影响,但并不完全是我想要的。现在我的 GUI 无法正确调整大小。我提供的 PreferredSize 是组件所保持的大小。我需要我的组件占据所有水平空间。如果我的显示区域尺寸增大或减小,我需要我的组件随之增大或减小,同时保持彼此的比例。
因此,我尝试再次重读教程并发现以下引用。
例如,要让按钮4变得特别高,示例中有这样的代码:
c.ipady = 40;
所以,我尝试了ipadx,但它没有改变任何东西。它看起来和我的前两次尝试一样。
最后,我尝试再次重读教程,但似乎没有其他方法适合我的解决方案。
有什么建议吗?
我重新创建了你的 GUI 以获得以下内容。
当您展开窗口时,组件也会展开。
所有 Swing 应用程序都必须以调用
SwingUtilities
invokeLater
方法开始。此方法确保 Swing 组件在 Event Dispatch Thread 上创建并执行。
每个人
JPanel
使用 GridBagLayout
。主要 JPanel
使用 GridBagLayout
。
这是完整的可运行代码。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GridBagLayoutTest5 implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new GridBagLayoutTest5());
}
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.gridx = 0;
gbc.gridy = 0;
panel.add(createButtonPanel(Color.BLUE,
"This is really long button text"), gbc);
gbc.gridx++;
panel.add(createButtonPanel(Color.RED, "This is button text"), gbc);
gbc.gridx = 0;
gbc.gridy++;
panel.add(createButtonPanel(Color.BLUE,
"This is really long button text"), gbc);
gbc.gridx++;
panel.add(createButtonPanel(Color.RED, "This is button text"), gbc);
return panel;
}
private JPanel createButtonPanel(Color color, String text) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createLineBorder(color, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.weightx = 1.0;
gbc.weighty = 1.0;
for (int index = 0; index < 16; index++) {
gbc.gridx = index % 4;
gbc.gridy = index / 4;
panel.add(createTextButton(text), gbc);
}
return panel;
}
private JButton createTextButton(String text) {
String s = "<html>" + text + "<br>" + text + "<br>";
s += text + "<br>" + text + "<br></html>";
JButton button = new JButton(s);
return button;
}
}