我有一个任务,需要使用 JavaSwing 复制特定布局。我决定使用 GridBagLayout,因为它看起来非常灵活,但当我尝试添加另一个具有自己的布局的 JPanel 作为网格的一部分时,它没有按预期响应。
代码如下:
/*
* GridBagLayoutDemo.java requires no other files.
*/
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JavaSwingLayout {
final static boolean shouldFill = true;
final static boolean shouldWeightX = true;
final static boolean RIGHT_TO_LEFT = false;
public static void addComponentsToPane(Container pane) {
if (RIGHT_TO_LEFT) {
pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}
JLabel label;
JPanel section;
Color color;
pane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
if (shouldFill) {
// natural height, maximum width
c.fill = GridBagConstraints.VERTICAL;
}
// Turquoise
label = new JLabel();
label.setOpaque(true);
color = new Color(76, 235, 169);
label.setBackground(color);
c.fill = GridBagConstraints.VERTICAL;
c.gridx = 0;
c.gridy = 0;
c.gridheight = 4;
c.ipadx = 150;
c.ipady = 100;
c.insets = new Insets(5, 5, 5, 5);
pane.add(label, c);
// Section
section = new JPanel();
section.setLayout(new GridBagLayout());
c.fill = GridBagConstraints.NONE;
c.gridx = 0;
c.gridy = 4;
c.gridheight = 4;
c.ipadx = 0;
c.ipady = 0;
c.weighty = 0;
c.weightx = 0;
c.insets = new Insets(0, 0, 0, 0);
pane.add(section, c);
// red
label = new JLabel();
label.setOpaque(true);
color = new Color(254, 0, 0);
label.setBackground(color);
c.fill = GridBagConstraints.VERTICAL;
c.gridx = 0;
c.gridy = 0;
c.gridheight = 1;
c.ipadx = 50;
c.ipady = 33;
c.insets = new Insets(0, 0, 0, 0);
section.add(label, c);
// orange
label = new JLabel();
label.setOpaque(true);
label.setOpaque(true);
color = new Color(255, 109, 0);
label.setBackground(color);
c.fill = GridBagConstraints.BOTH;
c.gridx = 0;
c.gridy = 1;
c.gridheight = 2;
c.ipadx = 0;
c.ipady = 0;
section.add(label, c);
//magenta
label = new JLabel();
label.setOpaque(true);
label.setOpaque(true);
color = new Color(240, 0, 255);
label.setBackground(color);
c.fill = GridBagConstraints.BOTH;
c.gridx = 1;
c.gridy = 0;
c.gridheight = 3;
c.gridwidth = 2;
c.ipadx = 100;
c.ipady = 100;
section.add(label, c);
// Green
label = new JLabel();
label.setOpaque(true);
color = new Color(56, 120, 0);
label.setBackground(color);
c.fill = GridBagConstraints.VERTICAL;
c.gridx = 1;
c.gridy = 0;
c.gridheight = 2;
c.ipadx = 100;
c.ipady = 50;
c.insets = new Insets(5, 5, 5, 5);
pane.add(label, c);
// Blue
label = new JLabel();
label.setOpaque(true);
color = new Color(1, 80, 159);
label.setBackground(color);
c.fill = GridBagConstraints.VERTICAL;
c.gridx = 1;
c.gridy = 2;
c.gridheight = 5;
c.ipady = 115;
pane.add(label, c);
// Tan
label = new JLabel();
label.setOpaque(true);
color = new Color(201, 157, 97);
label.setBackground(color);
c.fill = GridBagConstraints.VERTICAL;
c.gridx = 1;
c.gridy = 7;
c.gridheight = 1;
c.ipady = 25;
pane.add(label, c);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("GridBagLayoutDemo");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Set up the content pane.
addComponentsToPane(frame.getContentPane());
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
输出如下图所示:
但是我希望 JPanel 称为具有自己的 GridBagLayout 的部分不要像那样垂直拉伸 JLabel 之间的空间,我希望它占据与上面的绿松石色 JLabel 相同的空间。
在将 JLabels 添加到 JPanel 部分之前,它看起来像这样:
但是添加它们之后,它扭曲了它应该占用的空间,并且尽管我尝试了很多,但似乎无法修复它。
尝试将其添加到
addComponentsToPane
的底部:
for (int y = 0; y < 8; y++) {
pane.add(Box.createVerticalStrut(0), new GridBagConstraints(
2, y, 0, 1, 0, 1,
GridBagConstraints.CENTER, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0));
}
我认为您正在接近布局,就像在方格纸上填充单元格一样。为了让 GridBagLayout 以同样的方式处理它:它有助于在 8 行的每一行上放置一些东西。因此,使用这段代码:我们在每一行添加一个空的 0x0 框。这有助于强制 GridBagLayout 按照您的方式来考虑每一行。
通过此更改:绿松石框和
section
应 分配 相同的高度。但是 section
还没有填满它的高度。如果(?)您希望它填充该高度,您可以首先添加:
c.fill = GridBagConstraints.VERTICAL;
section.setBorder(new LineBorder(Color.black));
pane.add(section, c);
边框有助于确认
section
已拉伸到适当的高度。然后,您需要进入 section
的布局内部,并为所有这些元素赋予 y 权重并填充,以便它们能够拉伸以填充可用空间。
除非您有迫切需要以这种方式处理它:我建议不要使用一个 GridBagLayout 来实现此 UI。 GridBagLayouts 可能很脆弱/棘手;如果修改一个单元格的一项属性,可能会破坏其他单元格。
如果您使用嵌套面板来实现此目的:我认为您可以避免使用 GridBagLayouts 并在 3 个面板中的 2 个中使用其更简单的表兄弟
GridLayout
。我会尝试类似的事情:
JPanel outermostRow = new JPanel(new GridLayout(1,2));
outermostRow.add(createLeftColumn());
outermostRow.add(createRightColumn());
private static JPanel createLeftColumn() {
JPanel returnValue = new JPanel(new GridLayout(2, 1));
returnValue.add(turquoiseBox);
returnValue.add(section);
return returnValue;
}