GridBagLayout 居中组件

GridBagLayout centering components

我已经尝试了一段时间才能完成这项工作。 我在网上看了很多教程和例子,似乎没有什么帮助。

组合框和标签都在框架中间彼此居中。

我知道需要有一个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);
    } 
}

Also why would it be in the center? Shouldnt it be in the top left if anything?

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

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

下面会将组件移动到容器的top/left点...

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 本身,我很想更改 weightx/yanchor 属性 panel本身当你把它添加到框架中时,它会变得更简单

so if I wanted to let say build a calculator with positioning the buttons in specific areas, essentially transforming the entire panel into one big grid and plotting my containers inside that grid what would be the best layout to use and how would I do that?

这最终取决于您希望 UI 看起来像什么。如果你只想让所有的按钮均匀占据可用的 space,也许 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 按钮周围留出两个空的 space,这是 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 非常强大和灵活,但也很复杂。

注意:我本可以使用两个面板和两个 GridLayout 来完成第二个布局——这是一个重要的概念,您不必拘泥于单个布局管理器,您可以使用多个面板, 每个都使用不同的布局管理器 "compound" 它们一起产生一个丰富的界面

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

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