【问题标题】:GridBagLayout gridding not workingGridBagLayout 网格不起作用
【发布时间】:2023-03-21 01:21:01
【问题描述】:

我正在尝试创建以下 GUI:

但我制作的 GUI 是:

我的网格是什么样子的:

图片:THE GRIDLAYOUT FOR THIS

我不明白为什么我会得到这个输出,因为我已经绘制了一个图表来帮助代码并且它似乎可以解决。

addCompadd 方法将输入组件添加到输入面板中给定的 (x, y) 位置和给定的组件宽度和高度。

代码:

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

public class GUIError extends JFrame {

    //initialise all the components
    JPanel mainPanel = new JPanel();
    JTextField txtDisplay = new JTextField();
    JButton btnA = new JButton("A");
    JButton btnB = new JButton("B");
    JButton btnC = new JButton("C");
    JButton btnD = new JButton("D");
    JButton btnE = new JButton("E");
    JButton btnF = new JButton("F");
    JButton btnWA = new JButton("WA");
    JButton btnWB = new JButton("WB");
    JButton btnWC = new JButton("WC");
    JButton btnWD = new JButton("WD");

    private void addComp(JPanel panel, JComponent comp, int xPos, int yPos, int compWidth, int compHeight) {

        GridBagConstraints gridConstraints = new GridBagConstraints();

        gridConstraints.gridx = xPos;
        gridConstraints.gridy = yPos;
        gridConstraints.gridwidth = compWidth;
        gridConstraints.gridheight = compHeight;
        gridConstraints.weightx = 0.5;
        gridConstraints.weighty = 0.5;
        gridConstraints.insets = new Insets(5, 5, 5, 5);
        gridConstraints.anchor = GridBagConstraints.CENTER;
        gridConstraints.fill = GridBagConstraints.BOTH;

        panel.add(comp, gridConstraints);

    }


    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        }
        catch (Exception e) { }

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {

                // create frame
                JFrame frame = new JFrame("Calculator");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                Container c = frame.getContentPane();

                // create GUI within frame              
                new GUIError(c);

                // finish frame definition
                frame.pack();
                frame.setResizable(false);
                frame.setVisible(true);

            }

        });
    }

    public GUIError(Container cont) {

        cont.setPreferredSize(new Dimension(610, 250));

        // parent panel containes every other panel
        mainPanel.setLayout(new GridBagLayout());

        // text display
        txtDisplay.setEditable(false);
        addComp(mainPanel, txtDisplay, 0, 0, 12, 2); // width 16, height 2


        addComp(mainPanel, btnA, 0, 2, 2, 1);
        addComp(mainPanel, btnB, 2, 2, 2, 1);
        addComp(mainPanel, btnC, 4, 2, 2, 1);
        addComp(mainPanel, btnD, 6, 2, 2, 1);
        addComp(mainPanel, btnE, 8, 2, 2, 1);
        addComp(mainPanel, btnF, 10, 2, 2, 1);
        addComp(mainPanel, btnWA, 0, 3, 3, 1);
        addComp(mainPanel, btnWB, 3, 3, 3, 1);
        addComp(mainPanel, btnWC, 6, 3, 3, 1);
        addComp(mainPanel, btnWD, 9, 3, 3, 1);

        cont.add(mainPanel);
    }
}

【问题讨论】:

  • GBC 是基于列的,+1 表示问题和 SSCCE/MCVE,开发 MigLayout (e.i.) 的原因
  • 不要以为只用 1 个面板就可以做到这一点。据我所知,gridwidth 无法指定“半个网格”。我认为最好的选择是使用不同的布局,或者将您的组件分成不同的面板(主面板在顶部包含一个字段,在下面包含 2 个面板(并排)。每个子面板有 2 个面板:一个用于 3较小的按钮,一个下面有 2 个较大的按钮)
  • 我没有使用gridwidth指定半个网格。第一行按钮是gridwidth = 2,第三行按钮是gridwidth = 3。我不明白你说的底部3个小按钮和2个大按钮是什么意思?我还链接的网格显示了我在这种情况下使用的网格。第二排按钮大小相同,第三排按钮大小相同。我不明白为什么这不适用于 GridBagLayout。
  • @user3749872 查看你要的结果;您希望 WAWB 占用与其他 3 个按钮相同的空间。正如您所获得的结果所见,您的组件似乎已锁定到位(与其他所有组件对齐)。由于您的小按钮,您有 6 个网格空间;您希望WA 占用下面网格空间的 1 1/2,而 WB 占用另外 1 1/2(与 WC 和 WD 相同)。在代码中,您没有尝试占用半个网格,但您要求的结果需要它。这可以通过切换布局或用面板分隔来完成
  • 我将发布一个解释的答案以及解决方案。给我一秒钟

标签: java swing layout layout-manager gridbaglayout


【解决方案1】:

@Matthieu 写道 -

您能否详细说明 GBC 是基于列的?这听起来像一个 我注意到的一个问题的解释......

我认为这种方式是 GridBagLayout 设计的,我一直使用 JLabels(没有边框:-)作为矩阵 ...

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

public class CopyTextNorthPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private JLabel hidelLabel;
    private JLabel firstLabel;
    private JTextField firstText;

    public CopyTextNorthPanel() {

        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        for (int k = 0; k < 50; k++) {
            hidelLabel = new JLabel("     ");
            hidelLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.weightx = 0.5;
            gbc.weighty = 0.5;
            gbc.gridx = k;
            gbc.gridy = 0;
            add(hidelLabel, gbc);
        }
        for (int k = 0; k < 5; k++) {
            firstLabel = new JLabel("Testing Label : ", SwingConstants.RIGHT);
            firstLabel.setFont(new Font("Serif", Font.BOLD, 20));
            firstLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.insets = new Insets(0, 0, 5, 0);
            gbc.gridx = 0;
            gbc.gridwidth = 8;
            gbc.gridy = k + 1;
            add(firstLabel, gbc);
        }
        for (int k = 0; k < 5; k++) {
            firstText = new JTextField("Testing TextField");
            firstText.setFont(new Font("Serif", Font.BOLD, 20));
            firstText.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.insets = new Insets(0, 0, 5, 0);
            gbc.gridx = 9;
            gbc.gridwidth = k + 8;
            gbc.gridy = k + 1;
            add(firstText, gbc);
        }
        for (int k = 0; k < 5; k++) {
            firstLabel = new JLabel("Testing Label : ", SwingConstants.RIGHT);
            firstLabel.setFont(new Font("Serif", Font.BOLD, 20));
            firstLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.insets = new Insets(0, 0, 5, 0);
            gbc.gridx = 20 + k;
            gbc.gridwidth = 8;
            gbc.gridy = k + 1;
            add(firstLabel, gbc);
        }
        for (int k = 0; k < 5; k++) {
            firstText = new JTextField("Testing TextField");
            firstText.setFont(new Font("Serif", Font.BOLD, 20));
            firstText.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.insets = new Insets(0, 0, 5, 0);
            gbc.gridx = 29 + k;
            gbc.gridwidth = 21 - k;
            gbc.gridy = k + 1;
            add(firstText, gbc);
        }
    }
}

【讨论】:

    【解决方案2】:

    如果您仍然有兴趣了解您的错误: grid'布局不是FlowLayout,你不能简单地添加组件,它会在程序读取它的同一时刻绘制对象。在网格的情况下,虚拟机首先读取所有对象,然后构建网格,列数是根据列数最多的那些行来确定的。因此,您最好选择 12 列(因此您可以避免创建新的“面板”和备用系统资源),但要做到这一点,您只需在其中一行

        // text display
        txtDisplay.setEditable(false);
        addComp(mainPanel, txtDisplay, 0, 0, 12, 2); // width 16, height 2
    
    
    
        //now go with empty spaces
        for(int i=0;i<12;i++){
            GridBagConstraints gridConstraints = new GridBagConstraints();
            gridConstraints.gridx = i;    //12 times "i"
            gridConstraints.gridy = 1;  //you left y=1 empty, so why don't use it
            gridConstraints.gridwidth = 1;  //one column = one space in grid
            gridConstraints.gridheight = 0;  //we don't want it to occupied any space
            gridConstraints.weightx = 0.5;
            gridConstraints.weighty = 0.5;
            gridConstraints.insets = new Insets(0, 0, 0, 0); //same reason, we don't want it to occupied any space
            gridConstraints.anchor = GridBagConstraints.CENTER;
            gridConstraints.fill = GridBagConstraints.BOTH ;
    
            mainPanel.add(Box.createHorizontalGlue(), gridConstraints);
        }
    
    
        addComp(mainPanel, btnA, 0, 2, 2, 1);
        addComp(mainPanel, btnB, 2, 2, 2, 1);
        addComp(mainPanel, btnC, 4, 2, 2, 1);
        addComp(mainPanel, btnD, 6, 2, 2, 1);
        addComp(mainPanel, btnE, 8, 2, 2, 1);
        addComp(mainPanel, btnF, 10, 2, 2, 1);
        addComp(mainPanel, btnWA, 0, 3, 3, 1);
        addComp(mainPanel, btnWB, 3, 3, 3, 1);
        addComp(mainPanel, btnWC, 6, 3, 3, 1);
        addComp(mainPanel, btnWD, 9, 3, 3, 1);
    

    【讨论】:

      【解决方案3】:

      通常我会制作单独的面板,但是嘿,谁不喜欢挑战呢?

      问题是某些列没有为 GBL 明确定义(没有单个组件定义其宽度),因此按钮 WA 不知道要覆盖按钮 B 的一半等多远。

      所以,我在组成所需部分的列中添加了一些零宽度的分隔符。

      多合一面板:

      import java.awt.*;
      import javax.swing.*;
      
      public class GridBagDemo3 implements Runnable
      {
        private JPanel panel;
      
        public static void main(String[] args)
        {
          SwingUtilities.invokeLater(new GridBagDemo3());
        }
      
        public void run()
        {
          JTextArea text = new JTextArea(10,10);
          JButton btnA = new JButton("A");
          JButton btnB = new JButton("B");
          JButton btnC = new JButton("C");
          JButton btnD = new JButton("D");
          JButton btnE = new JButton("E");
          JButton btnF = new JButton("F");
          JButton btnWA = new JButton("WA");
          JButton btnWB = new JButton("WB");
          JButton btnWC = new JButton("WC");
          JButton btnWD = new JButton("WD");
      
          panel = new JPanel(new GridBagLayout());
      
          add(text,   0,0, 12,1);
          add(btnA,   0,1, 2,1);
          add(btnB,   2,1, 2,1);
          add(btnC,   4,1, 2,1);
          add(btnD,   6,1, 2,1);
          add(btnE,   8,1, 2,1);
          add(btnF,  10,1, 2,1);
          add(btnWA,  0,2, 3,1);
          add(btnWB,  3,2, 3,1);
          add(btnWC,  6,2, 3,1);
          add(btnWD,  9,2, 3,1);
      
          // SPACERS: define the 2 columns that button B spans
          //          so that WA and WB can split B, and same for button E
          add(null,   2,2, 1,1);
          add(null,   3,2, 1,1);
          add(null,   8,2, 1,1);
          add(null,   9,2, 1,1);
      
          JFrame frame = new JFrame("Grig Bag");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(panel);
          frame.pack();
          frame.setVisible(true);
        }
      
        private void add(Component comp, int x, int y, int colspan, int rowspan)
        {
          GridBagConstraints gbc = new GridBagConstraints();
          gbc.gridx = x;
          gbc.gridy = y;
          gbc.gridwidth = colspan;
          gbc.gridheight = rowspan;
          gbc.weighty = .1;
          gbc.anchor = GridBagConstraints.CENTER;
          gbc.fill = GridBagConstraints.BOTH;
          gbc.insets = new Insets(5,5,5,5);
      
          if (comp != null)
          {
            gbc.weightx = 1;
          }
          else
          {
            comp = Box.createHorizontalGlue();
            gbc.fill = GridBagConstraints.NONE;
            gbc.weightx = 0.1;
            gbc.weighty = 0;
          }
      
          panel.add(comp, gbc);
        }
      }
      

      【讨论】:

        【解决方案4】:

        可以通过使用GridBagLayout 轻松实现,如下面的示例所示。您只需为每个ROW 取两个JPanel。两者都使用GridBagLayout,并将组件添加到第一行,weightx = 0.16 因为每个JButton 都假设占用这么多区域,第二行 weightx = 0.25 因为这是每个JButton沿X方向

        占据的区域
        import java.awt.*;
        import java.awt.event.*;
        import javax.swing.*;
        
        public class GridBagExample {
            private static final int SIZE = 10;
            private JButton[] buttons;
            private GridBagConstraints gbc;
        
            public GridBagExample() {
                buttons = new JButton[SIZE];
                gbc = new GridBagConstraints();
                gbc.insets = new Insets(5, 5, 5, 5);
            }
        
            private void createAndDisplayGUI() {
                JFrame frame = new JFrame("Grid Game");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        
                JPanel contentPane = new JPanel();
                contentPane.setLayout(new GridLayout(2, 1, 5, 5));
                contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
                JPanel topPanel = new JPanel();
                JTextField textField = new JTextField(10);
                //topPanel.add(textField);
        
                JPanel buttonPanel = new JPanel(new GridLayout(2, 1, 5, 5));
                JPanel headerPanel = new JPanel(new GridBagLayout());
                buttons[0] = new JButton("A");
                addComp(headerPanel, buttons[0], 0, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);        
                buttons[1] = new JButton("B");
                addComp(headerPanel, buttons[1], 1, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
                buttons[2] = new JButton("C");
                addComp(headerPanel, buttons[2], 2, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
                buttons[3] = new JButton("D");
                addComp(headerPanel, buttons[3], 3, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
                buttons[4] = new JButton("E");
                addComp(headerPanel, buttons[4], 4, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
                buttons[5] = new JButton("F");
                addComp(headerPanel, buttons[5], 5, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
        
                JPanel footerPanel = new JPanel(new GridBagLayout());
                buttons[6] = new JButton("WA");
                addComp(footerPanel, buttons[6], 0, 0, 0.25, 1.0, 1, 1, GridBagConstraints.BOTH);
                buttons[7] = new JButton("WB");
                addComp(footerPanel, buttons[7], 1, 0, 0.25, 1.0, 1, 1, GridBagConstraints.BOTH);
                buttons[8] = new JButton("WC");
                addComp(footerPanel, buttons[8], 2, 0, 0.25, 1.0, 1, 1, GridBagConstraints.BOTH);
                buttons[9] = new JButton("WD");
                addComp(footerPanel, buttons[9], 3, 0, 0.25, 1.0, 1, 1, GridBagConstraints.BOTH);
                buttonPanel.add(headerPanel);
                buttonPanel.add(footerPanel);
        
                contentPane.add(textField);
                contentPane.add(buttonPanel);
        
                frame.setContentPane(contentPane);
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        
            private void addComp(JPanel panel, JComponent comp, int x, int y,
                                            double wx, double wy, int gw, int gh, int fill) {
                gbc.gridx = x;
                gbc.gridy = y;
                gbc.weightx = wx;
                gbc.weighty = wy;
                gbc.gridwidth = gw;
                gbc.gridheight = gh;
                gbc.fill = fill;
        
                panel.add(comp, gbc);
            }
        
            public static void main(String... args) {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        new GridBagExample().createAndDisplayGUI();
                    }
                });
            }
        }
        

        输出: GRIDBAGLAYOUT:

        如果GridBagLayout 在这种情况下不是必需的,GridLayout 可以实现相同的输出,如下例所示:

        import java.awt.*;
        import java.awt.event.*;
        import javax.swing.*;
        
        public class GridBagExample {
            private static final int SIZE = 10;
            private JButton[] buttons;
        
            public GridBagExample() {
                buttons = new JButton[SIZE];
            }
        
            private void createAndDisplayGUI() {
                JFrame frame = new JFrame("Grid Game");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        
                JPanel contentPane = new JPanel();
                contentPane.setLayout(new GridLayout(2, 1, 5, 5));
                contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
                JPanel topPanel = new JPanel();
                JTextArea tArea = new JTextArea(5, 30);
                JScrollPane scroller = new JScrollPane();
                scroller.setViewportView(tArea);
                topPanel.add(scroller);
        
                JPanel buttonPanel = new JPanel(new GridLayout(2, 1, 5, 5));
                JPanel headerPanel = new JPanel(new GridLayout(1, 0, 5, 5));
                buttons[0] = new JButton("A");
                headerPanel.add(buttons[0]);
                buttons[1] = new JButton("B");
                headerPanel.add(buttons[1]);
                buttons[2] = new JButton("C");
                headerPanel.add(buttons[2]);
                buttons[3] = new JButton("D");
                headerPanel.add(buttons[3]);
                buttons[4] = new JButton("E");
                headerPanel.add(buttons[4]);
                buttons[5] = new JButton("F");
                headerPanel.add(buttons[5]);
                JPanel footerPanel = new JPanel(new GridLayout(1, 0, 5, 5));
                buttons[6] = new JButton("WA");
                footerPanel.add(buttons[6]);
                buttons[7] = new JButton("WB");
                footerPanel.add(buttons[7]);
                buttons[8] = new JButton("WC");
                footerPanel.add(buttons[8]);
                buttons[9] = new JButton("WD");
                footerPanel.add(buttons[9]);
                buttonPanel.add(headerPanel);
                buttonPanel.add(footerPanel);
        
                contentPane.add(topPanel);
                contentPane.add(buttonPanel);
        
                frame.setContentPane(contentPane);
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        
            public static void main(String... args) {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        new GridBagExample().createAndDisplayGUI();
                    }
                });
            }
        }
        

        输出: 网格布局:

        【讨论】:

          猜你喜欢
          • 2013-08-22
          • 2014-11-23
          • 2017-05-28
          • 1970-01-01
          • 1970-01-01
          • 2013-12-10
          • 2020-10-27
          • 2015-07-07
          • 2018-05-30
          相关资源
          最近更新 更多