如何将空单元格添加到GridBagLayout?

时间:2017-07-18 19:19:14

标签: java swing constraints layout-manager gridbaglayout

我想使用GridBagLayout实现此效果:

|-----------|
|  Button1  |
|-----------|
      |-----------|
      |  Button2  |
      |-----------|

我最初只是放置按钮,但GridBagLayout忽略了空单元格。现在,我试图使用Box.createHorizo​​ntalStrut(10)作为间隔符,但GridBagLayout正在拉伸空格给我一个2x2网格。我也试过JLabel和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);
    }
}

有什么想法吗?谢谢!

2 个答案:

答案 0 :(得分:3)

GridBagLayout取决于第一个词的含义;一个网格。为了达到您想要的效果,您实际上需要一个2x3网格:

        c1   | c2 |   c3
             |    |  
             v    v   
     |------------|
r1   |    B1      |  <S1>
     |------------|
---->
             |------------|
r2     <S2>  |    B2      |
             |------------|

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

基本上,我们说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);
  }
}

根据您的使用情况,使用其他答案中提到的插图也可能适用。

我要提醒的是,如果面板的布局本质上是动态的,您可能希望在面板中级联面板和布局。例如,要将给定的示例扩展为:

|-----------|
|  Button1  |
|-----------|
      |-----------|
      |  Button2  |
      |-----------|
            |-----------|
            |  Button3  |
            |-----------|

等等,单个面板处理变得有点麻烦(特别是如果需要动态处理; IE:在事件X发生时添加按钮4)。 insets方法可以更好地管理这个问题;你可以简单地迭代插入值。

更好的方法是IMO,而不是级联你的面板,以便每一行都由它自己的面板(和布局管理器)管理。

+-------MAIN PANEL----------+
| +------r1-----R1 PANEL---+|
| ||-----------|           ||
c1||  Button1  |           ||
| ||-----------|           ||
| +------------------------+|
| +---r1--------r2-R2 PANEL+|
| |       |-----------|    ||
c2|<STRUT>|  Button1  |    ||
| |       |-----------|    ||
| +------------------------+|
|  etc...                   |
+---------------------------+

希望有所帮助!

答案 1 :(得分:0)

原始回答

您可以使用GridBagConstraints.INSETS来实现此目的。在你的代码中我看到你总是将0传递给你的 placeComponent 方法,你只需要指定一个不同的值。 不需要Horizo​​ntalStruct或其他组件。

例如,在您的代码中,如果您使用:

placeComponent( button1, 0, 0, 2, 2, 0.5, 0.5, fill, 10, 10, 10, 10, anchor);
placeComponent( button2, 1, 2, 2, 2, 0.5, 0.5, fill, 50, 100, 10, 10, anchor);

您将获得:

enter image description here

请注意,由于您使用GridBagLayout作为内容窗格布局,因此窗口大小会扩展按钮。

如果您不希望button2小于button1,可以使用GridBagConstraints.NONE作为填充参数来避免这种情况。

修改

我根据您的评论编辑了我的答案。

当然可以避免使用GridBagLayout.NONE。

这完全取决于你想要达到的目标。 因此,您希望按钮具有相同的大小,并且在调整窗口大小时它们的大小会增长。还行吧。 但是你的button2应该如何在按钮1的右侧“移动”?按指定的像素数?

如果是这样,假设button2应该相对于button1向右移动100个像素。 这可以通过将第二个按钮左边的插图设置为100,然后将第一个按钮右边设为100(以保持相同的大小)来轻松实现。

如果在您的代码中替换了这四行:

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

使用:

placeComponent( button1, 0, 0, 2, 2, 0.5, 0.5, fill, 0, 0, 0, 100, anchor );
placeComponent( button2, 1, 2, 2, 2, 0.5, 0.5, fill, 50, 100, 0, 0, anchor );

您将得到以下结果:

enter image description here

这将是你调整大小的窗口:

enter image description here

如果这不是您想要达到的目标,那么您最好提供ASCII艺术品或者以最小尺寸简单绘制所需的GUI,并且具有更大的宽度和高度。

希望这有帮助!