【问题标题】:GridBagLayout centering componentsGridBagLayout 居中组件
【发布时间】:2018-08-23 03:57:18
【问题描述】:

我已经尝试了一段时间来完成这项工作。 我在网上看了很多教程和示例,似乎没有任何帮助。

组合框和标签都位于框架中间的正下方。

我知道需要GridBagConstraints,并且每次添加新组件时都需要设置gbc。

我正在这样做,所以我不确定为什么它不起作用。

还有为什么它会在中心? 如果有的话,它不应该在左上角吗?

public class Application {
ArrayList listOfTickers = new ArrayList();
JFrame frame;
JPanel panel;
JLabel jLabel;
GridBagLayout layout;
GridBagConstraints gbc;
JComboBox comboBox;


Application(ArrayList listOfTickers) throws BadLocationException {
    this.listOfTickers = listOfTickers;

    setLabels();
    setComboBox(listOfTickers);
    setFrameAndPanel();
    addComponents();
    closeFrame();
}

private void addComponents() {
    addobjects(jLabel, panel, layout, gbc, 1, 3, 4, 2);
    addobjects(comboBox, panel, layout, gbc, 3, 0, 2, 1);
}

private void setLabels() {
    jLabel = new JLabel("test");
}

private void closeFrame() {
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}

private void setComboBox(ArrayList listOfTickers) throws BadLocationException {
    comboBox = new JComboBox(listOfTickers.toArray());
    comboBox.addActionListener(e -> {
        String ticker = comboBox.getSelectedItem().toString();
    });
}

private void setFrameAndPanel() {
    frame = new JFrame("JFrame Example");
    panel = new JPanel();
    layout = new GridBagLayout();
    panel.setLayout(layout);
    frame.getContentPane().setLayout(layout);
    gbc = new GridBagConstraints();
    frame.add(panel);
    frame.setSize(600, 600);
}

public void addobjects(Component component, Container panel, GridBagLayout layout, GridBagConstraints gbc, int gridx, int gridy, int gridwidth, int gridheight) {

    gbc.gridx = gridx;
    gbc.gridy = gridy;

    gbc.gridwidth = gridwidth;
    gbc.gridheight = gridheight;

    layout.setConstraints(component, gbc);
    panel.add(component, gbc);
    } 
}

【问题讨论】:

  • “还有,为什么它会在中间?如果有的话,它不应该在左上角吗?” - 不,这就是GridBagLayout 的工作原理(而且,是的,是时候动动脑筋了)
  • 就我个人而言,我会避免使用addobjects 样式编码,因为它极大地限制了您可以做什么或要求您为每个可能的参数组合编写方法
  • 你还会发现gridWidthgridHeight 如果你使用不当会弄乱布局
  • 1) 为了尽快获得更好的帮助,请发帖 minimal reproducible exampleShort, Self Contained, Correct Example。 2) 以最小尺寸提供 ASCII 艺术或 GUI 的 预期 布局的简单绘图,如果可调整大小,则具有更大的宽度和高度 - 以显示应如何使用额外空间。

标签: java swing jpanel layout-manager gridbaglayout


【解决方案1】:

还有为什么它会在中心?如果有的话,它不应该在左上角吗?

不,这就是 GridBagLayout 的工作方式,GridBagLayout 将围绕container 的中心布置它的组件。您可以使用weightx/y 属性来更改分配给给定单元格的剩余空间量。

我还建议避免使用 gridwidthgridheight,直到您更好地了解它们的作用,因为它们会影响组件的位置

以下将组件移动到容器的顶部/左侧点...

private void addComponents() {
    gbc.gridx = 1;
    gbc.gridy = 3;
    gbc.weighty = 1;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    panel.add(jLabel, gbc);

    gbc.gridx = 3;
    gbc.gridy = 0;
    gbc.anchor = GridBagConstraints.WEST;
    gbc.weightx = 1;
    gbc.weighty = 0;

    panel.add(comboBox, gbc);
}

虽然,由于您将GridBagLayout 应用于JFrame 本身,所以当您将panel 添加到框架时,我很想更改panel 本身的weightx/yanchor 属性,它会变得更简单

所以,如果我想说构建一个计算器,将按钮定位在特定区域,基本上将整个面板转换为一个大网格,并在该网格内绘制我的容器,什么是最好的布局,我会怎么做那个?

这最终取决于您希望用户界面是什么样子。如果您只想让所有按钮均匀地占据可用空间,那么GridLayout 可能会是更好的选择...

import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Application {
    public static void main(String[] args) {
        new Application();
    }

    public Application() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridLayout(4, 3));
            String labels[] = new String[] {"7", "8", "9", "4", "5", "6", "1", "2", "3", "", "0", ""};
            for (String label : labels) {
                if (label.trim().isEmpty()) {
                    add(new JLabel());
                } else {
                    add(new JButton(label));
                }
            }
        }

    }

}

注意,我必须在 0 按钮周围留出两个空格,这是GridLayout 的要求,因为您无法控制组件实际出现的单元格,它们只是以线性方式布置。

但是,如果您更喜欢看起来更像大多数计算器的东西,那么您需要GridBagLayout...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Application {

    public static void main(String[] args) {
        new Application();
    }

    public Application() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            String labels[][] = new String[][]{{"7", "8", "9"}, {"4", "5", "6"}, {"1", "2", "3"}};
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridy = 0;
            for (String[] row : labels) {
                gbc.gridx = 0;
                for (String col : row) {
                    add(new JButton(col), gbc);
                    gbc.gridx++;
                }
                gbc.gridy++;
            }
            gbc.gridx = 0;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.gridwidth = 3;
            add(new JButton("0"), gbc);
        }

    }

}

需要驱动必须,您需要决定是否需要灵活性而不是一致性(在这种情况下)。 GridBagLayout 非常强大和灵活,但也带来了复杂性。

注意:我也可以使用两个面板和两个GridLayouts 来完成第二个布局 - 这是一个重要的概念,您不会局限于一个布局管理器,您可以使用多个面板,每个面板使用不同的布局管理器并将它们“组合”在一起以产生丰富的界面

【讨论】:

  • 谢谢,所以如果我想说构建一个将按钮定位在特定区域的计算器,基本上将整个面板转换为一个大网格,并在该网格内绘制我的容器什么是最好的要使用的布局以及我将如何做到这一点。我最初的想法是这是最好的布局。但是现在我看到了您发布的内容,似乎这可能不是最佳选择。谢谢。
  • 很大程度上取决于您的最终目标,例如,如果您只希望所有按钮大小相同并均匀占用容器的可用空间,那么GridLayout 可能是更好的选择,但是,如果你想像大多数计算器 UI 一样,允许 0 按钮比其他按钮扩展更多空间,那么 GridBagLayout 是你需要去的方向
【解决方案2】:

如果您要进行大量 UI 构建,下载 Netbeans IDE 并学习使用它的 GUI 构建器对您大有裨益。它是一个出色的 GUI 构建器,您在调整布局参数时获得的视觉反馈对于了解 UI 构建的窍门非常有帮助,尤其是对于了解各种 GridBagLayout 参数的工作原理非常有帮助。它比“write-run-tweak-rerun”循环更有效。

手动编写 UI 代码是我最不喜欢的事情。如果可能的话,不要把它强加给自己!

【讨论】:

    猜你喜欢
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2018-01-13
    • 2011-11-08
    • 2022-01-08
    • 2022-01-12
    • 1970-01-01
    相关资源
    最近更新 更多