如何向 GridBagLayout 添加空单元格?

Bir*_*man 2 java swing constraints layout-manager gridbaglayout

我想使用GridBagLayout来实现这种效果:

|-----------|
|  Button1  |
|-----------|
      |-----------|
      |  Button2  |
      |-----------|
Run Code Online (Sandbox Code Playgroud)

我最初只是放置了按钮,但 GridBagLayout 忽略了空单元格。现在,我尝试使用 Box.createHorizo​​ntalStrut(10) 作为间隔符,但 GridBagLayout 正在拉伸空间以给我一个 2x2 网格。我还尝试了 JLabels 和 JPanels 作为间隔物,但我仍然得到 2x2 网格。这是我的代码:

import java.awt.*;
import javax.swing.*;

public class GridBagLayoutDemo extends JFrame
{
    // class level references
    GridBagLayout layout;   
    JButton button1, button2;

    // constructor
    public GridBagLayoutDemo()
    {
        super("GridBagLayout Demo");

        layout = new GridBagLayout();
        setLayout( layout );

        // create components
        button1 = new JButton("Button 1");
        button2 = new JButton("Button 2");

        // components should be resized vertically AND horizontally (BOTH) to fill given area
        int fill = GridBagConstraints.BOTH;

        // if you do not fill the area, where should the component go?
        int anchor = GridBagConstraints.CENTER;

        // place components on the frame using a method
        placeComponent( button1, 0, 0, 2, 2, 0.5, 0.5, fill, 0, 0, 0, 0, anchor );
        placeComponent( Box.createHorizontalStrut(5), 2, 0, 1, 2, 0.5, 0.5, fill, 0, 0, 0, 0, anchor );
        placeComponent( Box.createHorizontalStrut(5), 0, 2, 1, 2, 0.5, 0.5, fill, 0, 0, 0, 0, anchor );
        placeComponent( button2, 1, 2, 2, 2, 0.5, 0.5, fill, 0, 0, 0, 0, anchor );
    }

    /// Place the component on the GridBag with appropriate parameters
    private void placeComponent( Component comp, int column, int row, int width, int height, double weightX, double weightY, 
            int fill, int marginTop, int marginLeft, int marginBottom, int marginRight, int anchor )
    {
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.gridx = column;     // column to start
        constraints.gridy = row;        // row to start
        constraints.gridwidth = width;  // number of cells wide
        constraints.gridheight = height;  // number of cells tall
        constraints.weightx = weightX;    // when size is changed, grow in x direction
        constraints.weighty = weightY;    // when size is changed, grow in y direction
        constraints.fill = fill;        // should the component fill the given area?  GridBagConstraints.NONE, GridBagConstraints.BOTH, GridBagConstraints.CENTER, etc
        constraints.insets = new Insets( marginTop, marginLeft, marginBottom, marginRight );
        constraints.anchor = anchor;
        layout.setConstraints(comp, constraints);
        add(comp);  // place component on the frame with these parameters
    }

    /// launches the application
    public static void main(String[] args)
    {
        GridBagLayoutDemo app = new GridBagLayoutDemo();
        app.setSize(400, 300);
        app.setLocationRelativeTo(null);
        app.setVisible(true);
    }
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?谢谢!

Iro*_*che 5

GridBagLayout 根据第一个单词的含义进行工作;一个网格。为了实现上面你想要的效果,你实际上需要一个2x3的网格:

        c1   | c2 |   c3
             |    |  
             v    v   
     |------------|
r1   |    B1      |  <S1>
     |------------|
---->
             |------------|
r2     <S2>  |    B2      |
             |------------|
Run Code Online (Sandbox Code Playgroud)

2x1 或 2x2 网格无法实现所需的偏移效果(如果您希望按钮重叠)。我们需要第三列才能获得按钮的重叠。

在此范例中,您有以下内容:

comp    | x    | y    | w    | h
------------------------------------
B1      | 0    | 0    | 2    | 1
S1      | 2    | 0    | 1    | 1
S2      | 0    | 1    | 1    | 1
B2      | 1    | 1    | 2    | 1
Run Code Online (Sandbox Code Playgroud)

基本上,我们说 B1 占据 [r1, c1-c2],S1 占据 [r1, c3],S2 占据 [r2, c1],B2 占据 [r2, c2-c3]。希望这是清楚的。

下面的 MCVE 说明了如何实现这一目标。您可以相当轻松地将其应用到您的代码中:

public class StaggerTest {
  public static void main(String[] args) {
    JFrame frame = new JFrame("Stagger Test");
    frame.setSize(600, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel panel = new JPanel(new GridBagLayout());

    placeComp(new JButton("1"), panel, 0, 0, 2, 1);
    placeComp(Box.createHorizontalStrut(10), panel, 2, 0, 1, 1);
    placeComp(Box.createHorizontalStrut(10), panel, 0, 1, 1, 1);
    placeComp(new JButton("2"), panel, 1, 1, 2, 1);

    frame.setContentPane(panel);

    frame.setVisible(true);
  }

  public static void placeComp(Component comp, JPanel panel, int x, int y, int w, int h) {
    GridBagConstraints cons = new GridBagConstraints();
    cons.gridx = x;
    cons.gridy = y;
    cons.gridwidth = w;
    cons.gridheight = h;
    panel.add(comp, cons);
  }
}
Run Code Online (Sandbox Code Playgroud)

正如其他答案中提到的,使用插图也可能适用,具体取决于您的用例。

我要注意的一件事是,如果面板的布局本质上是动态的,您可能需要级联面板和面板内的布局。例如,将给定示例扩展为:

|-----------|
|  Button1  |
|-----------|
      |-----------|
      |  Button2  |
      |-----------|
            |-----------|
            |  Button3  |
            |-----------|
Run Code Online (Sandbox Code Playgroud)

等等,用单个面板处理会变得有点混乱(特别是如果需要动态处理;IE:当事件 X 发生时添加按钮 4)。插图方法可以更好地解决这个问题;您可以简单地迭代插入值。

在我看来,更好的方法是级联面板,以便每一行都由自己的面板(和布局管理器)管理。

+-------MAIN PANEL----------+
| +------c1-----R1 PANEL---+|
| ||-----------|           ||
r1||  Button1  |           ||
| ||-----------|           ||
| +------------------------+|
| +---c1--------c2-R2 PANEL+|
| |       |-----------|    ||
r2|<STRUT>|  Button1  |    ||
| |       |-----------|    ||
| +------------------------+|
|  etc...                   |
+---------------------------+
Run Code Online (Sandbox Code Playgroud)

希望有帮助!