Java GridBagLayout 不起作用

Posted

技术标签:

【中文标题】Java GridBagLayout 不起作用【英文标题】:Java GridBagLayout not working 【发布时间】:2014-11-23 04:24:10 【问题描述】:

我正在尝试使用GridBagLayout,但我没有得到预期的结果,并且在此代码中找不到错误:

public class GridBagEx1 extends JPanel 

    private static final long serialVersionUID = 1L;

    protected void makebutton(String name, GridBagLayout gridbag, GridBagConstraints c) 
        JButton button = new JButton(name);
        gridbag.setConstraints(button, c);
        add(button);
    

    public void init() 
        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        setLayout(gridbag);

        c.fill = BOTH;

        c.weightx = 1.0;
        c.weighty = 1.0;

        c.anchor = CENTER;

        c.insets.top = 5;
        c.insets.bottom = 5;
        c.insets.left = 5;
        c.insets.right = 5;

        c.gridx = 0;
        c.gridy = 0;
        c.gridheight = 1;
        c.gridwidth = 2;
        makebutton("Button1", gridbag, c);      

        c.gridx = 2;
        c.gridy = 0;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button2", gridbag, c);

        c.gridx = 3;
        c.gridy = 0;
        c.gridheight = 2;
        c.gridwidth = 2;
        makebutton("Button3", gridbag, c);

        c.gridx = 0;
        c.gridy = 1;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button4", gridbag, c);

        c.gridx = 1;
        c.gridy = 1;
        c.gridheight = 1;
        c.gridwidth = 2;
        makebutton("Button5", gridbag, c);

        c.gridx = 0;
        c.gridy = 2;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button6", gridbag, c);

        c.gridx = 1;
        c.gridy = 2;
        c.gridheight = 1;
        c.gridwidth = 2;
        makebutton("Button7", gridbag, c);

        c.gridx = 3;
        c.gridy = 2;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button8", gridbag, c);

        c.gridx = 4;
        c.gridy = 2;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button9", gridbag, c);
    

    public static void main(String args[]) 
        JFrame frame = new JFrame();
        GridBagEx1 ex1 = new GridBagEx1();

        ex1.init();

        frame.add(ex1);
        frame.pack();
        frame.setVisible(true);
    

这张图说明了我需要什么:

黄色为按钮名称,红色为行列。

这是真正发生的事情:

谁能解释我的代码有什么问题?

【问题讨论】:

我还不能解释这个问题,但必须说明你的问题很好地提出了,谢谢你和 1+。 @HovercraftFullOfEels 谢谢 c.fill = BOTH; 应该是 c.fill = GridBagConstraints.BOTH;c.anchor = CENTER; 相同,以便编译代码。 @user1803551 如果你不是 import static java.awt.GridBagConstraints.*; :-) @GeroldBroser 真...真... 【参考方案1】:

问题是没有什么可以说服第二个网格列 (gridx=1) 具有任何宽度,因为没有组件需要 适合第二列。因此,第二列的宽度为 0,因此尽管 Button1 确实跨越了前两列,但它看起来并不那样,因为它的所有宽度需求都由第一列满足;虽然 Button5 和 Button7 横跨第二列和第三列,但它们的所有宽度需求都由第三列满足。

要修复它,您必须说服应该更宽(1、5、7)的按钮占用更多空间。在这里,我通过设置c.ipadx = 35; 为这些按钮添加了填充。 (我还删除了weightx = 1.0 约束。由于我不太明白的原因,它在保留时不起作用。):

来源:

public void init() 
    GridBagLayout gridbag = new GridBagLayout();
    GridBagConstraints c = new GridBagConstraints();
    setLayout(gridbag);

    c.fill = c.BOTH;

    //c.weightx = 1.0;
    //c.weighty = 1.0;

    c.anchor = c.CENTER;

    c.insets.top = 5;
    c.insets.bottom = 5;
    c.insets.left = 5;
    c.insets.right = 5;

    c.gridx = 0;
    c.gridy = 0;
    c.gridheight = 1;
    c.gridwidth = 2;
    c.ipadx = 35;
    makebutton("Button1", gridbag, c);

    c.gridx = 2;
    c.gridy = 0;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button2", gridbag, c);

    c.gridx = 3;
    c.gridy = 0;
    c.gridheight = 2;
    c.gridwidth = 2;
    c.ipadx = 0;
    makebutton("Button3", gridbag, c);

    c.gridx = 0;
    c.gridy = 1;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button4", gridbag, c);

    c.gridx = 1;
    c.gridy = 1;
    c.gridheight = 1;
    c.gridwidth = 2;
    c.ipadx = 35;
    makebutton("Button5", gridbag, c);

    c.gridx = 0;
    c.gridy = 2;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button6", gridbag, c);

    c.gridx = 1;
    c.gridy = 2;
    c.gridheight = 1;
    c.gridwidth = 2;
    c.ipadx = 35;
    makebutton("Button7", gridbag, c);

    c.gridx = 3;
    c.gridy = 2;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button8", gridbag, c);

    c.gridx = 4;
    c.gridy = 2;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button9", gridbag, c);


编辑: 正如 cmets 中所指出的,上述方法不适合,因为它会阻止动态调整布局大小。要使布局扩展以填充其容器的大小,需要 weightxweighty 约束,但是第二列没有得到任何宽度。

这是一个替代解决方案的尝试。这是一个肮脏的 hack,它在第二列的底部插入一个不可见的组件以强制该列具有宽度:

    c.gridx = 1;
    c.gridy = 3;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.insets.set(0, 0, 0, 0);
    c.weighty = 0;
    add(Box.createRigidArea(new Dimension(50, 0)), c);

这在调整窗口大小时可以很好地应对,因为尽管组件具有固定的初始大小,但 GridBagLayout 会与其他组件成比例地放大它。不过,它仍然不完美。也许有更好的解决方案,但我找不到。

【讨论】:

@FilipB.Vondrášek 我不认为 this 一个具有特定(相当复杂)布局管理器的特殊情况 总结 并证明 Swing 是可憎的。当然 Swing 有其优点和缺点,但这并不是秘密,每个人都知道。 @FilipB.Vondrášek 如果有一个非可恶的替代方案。 JavaFX 怎么样?不过,从来没有用过。 @Boann 删除重量,x 按钮不调整大小,如果您重新添加它们,此代码将不起作用! @Boann 另一件事,按钮本身没有尺寸,我希望 gridbaglayout 在 jpanel 的底部为它们分配一个尺寸!【参考方案2】:

我设法设计了 needed 布局,没有任何 hack 并通过使用 JGoodies FormLayout 支持动态调整大小:

import java.awt.Component;

import javax.swing.JButton;
import javax.swing.JPanel;

import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

public class FormLayoutPanel extends JPanel
    
    public FormLayoutPanel()
        
        setAlignmentY( Component.BOTTOM_ALIGNMENT );
        setAlignmentX( Component.RIGHT_ALIGNMENT );
        setLayout( new FormLayout( new ColumnSpec[] 
            ColumnSpec.decode( "41px:grow" ),
            FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
            ColumnSpec.decode( "25px:grow" ),
            FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
            ColumnSpec.decode( "41px:grow" ),
            FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
            ColumnSpec.decode( "41px:grow" ),
            FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
            ColumnSpec.decode( "41px:grow" ), ,
            new RowSpec[] 
                RowSpec.decode( "25px:grow" ),
                FormFactory.LINE_GAP_ROWSPEC,
                RowSpec.decode( "25px:grow" ),
                FormFactory.LINE_GAP_ROWSPEC,
                RowSpec.decode( "25px:grow" ),  ) );

        JButton button1 = new JButton( "1" );
        add( button1, "1, 1, 3, 1, fill, fill" );
        JButton button2 = new JButton( "2" );
        add( button2, "5, 1, fill, fill" );
        JButton button3 = new JButton( "3" );
        add( button3, "7, 1, 3, 3, fill, fill" );
        JButton button4 = new JButton( "4" );
        add( button4, "1, 3, fill, fill" );
        JButton button5 = new JButton( "5" );
        add( button5, "3, 3, 3, 1, fill, fill" );
        JButton button6 = new JButton( "6" );
        add( button6, "1, 5, fill, fill" );
        JButton button7 = new JButton( "7" );
        add( button7, "3, 5, 3, 1, fill, fill" );
        JButton button8 = new JButton( "8" );
        add( button8, "7, 5, fill, fill" );
        JButton button9 = new JButton( "9" );
        add( button9, "9, 5, fill, fill" );
        
    

【讨论】:

以上是关于Java GridBagLayout 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

GridBagLayout中的Make Component占用相同的宽度

为什么GridBagConstraints不起作用?

java中Swing的GridBagLayout使用简介

java GridBagLayout 锚点

在 java 中使用 GridBagLayout 时设置最大组件大小

Java 的布局管理器GridBagLayout的使用方法图文说明