GridBagLayout 如何将组件向北推

2024-01-07

这是我的代码

 public class HomeTopPanel extends JPanel {

//BUTTONS
private final JButton myAccountButton = new JButton("My Account");
private final JButton updatePhoto = new JButton("Update Photo");

//PANELS
private final JPanel rightPanel_1 = new JPanel(new GridBagLayout());
private final JPanel rightPanel_2 = new JPanel(new GridBagLayout());
private final JPanel logHistoryPanel = new JPanel(new GridBagLayout());

//BORDERS
private final Border homeTopPanel_LineBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
private final Border rightPanel1_LineBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
private final Border rightPanel2_LineBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
private final TitledBorder logHistoryPanel_TitledBorder = BorderFactory.createTitledBorder("Log History");

//LABELS
private final JLabel imageContainer = new JLabel("User Image");


//CONSTRAINTS
GridBagConstraints gbc = new GridBagConstraints();

//CONSTRUCTOR
public HomeTopPanel(){
    //METHOD CALLS
    this.setLayout(new GridBagLayout()); //setting of layout should ALWAYS come first before adding constraints and components
    constructMyAccountButton();
    constructRightPanel_1();
    constructRightPanel_2();
    constructLeftPanelComponents();
    setRightPanelBorders();
}

public final void constructMyAccountButton(){
    gbc.anchor = GridBagConstraints.PAGE_START;
    gbc.insets = new Insets(5,5,5,5);
    gbc.gridx = 0; gbc.gridy = 0; 
        this.add(myAccountButton,gbc);
}

public final void constructRightPanel_1(){
    rightPanel_1.setPreferredSize(new Dimension(1000, 550));
    gbc.gridx = 1; gbc.gridy = 0; 
        this.add(rightPanel_1,gbc);
}

public final void constructRightPanel_2(){
    rightPanel_2.setPreferredSize(new Dimension(800, 300));
    gbc.gridheight = 3;
        rightPanel_1.add(rightPanel_2,gbc);
}

public final void constructLeftPanelComponents(){
    gbc.gridx = 0; gbc.gridy = 0;
    gbc.ipadx = 0;
    gbc.anchor = GridBagConstraints.PAGE_START;
        rightPanel_1.add(imageContainer,gbc);
    gbc.gridx = 0; gbc.gridy = 1;
    gbc.anchor = GridBagConstraints.CENTER;
        rightPanel_1.add(updatePhoto,gbc);
    gbc.gridx = 0; gbc.gridy = 2;
    gbc.anchor = GridBagConstraints.PAGE_END;
        logHistoryPanel.setPreferredSize(new Dimension(110, 100));
        rightPanel_1.add(logHistoryPanel,gbc);
}

private void setRightPanelBorders(){
    rightPanel_1.setBorder(rightPanel1_LineBorder);
    rightPanel_2.setBorder(rightPanel2_LineBorder);
    logHistoryPanel.setBorder(logHistoryPanel_TitledBorder);
    this.setBorder(homeTopPanel_LineBorder);
}
}   

Here's what I get: enter image description here

我有两个问题:

  1. 如何将这 4 个对象全部推到顶部?
  2. 为什么“用户图像”JLabel 占用太多空间,或者为什么它的单元格高度太高?

我想完成这个:

然后将其推到顶部。我尝试使用插图和重量,但仍然无法得到我想要的结果。

我将不胜感激任何帮助。此时不知道是ipadx/ipady的问题还是weightx/weighty的问题。


  1. 如何将这 4 个对象全部推到顶部?

您需要为组件分配权重:gbc.weightx and gbc.weighty.

  1. 为什么“用户图像”JLabel 占用太多空间,或者为什么它的单元格高度太高?

你忘记重置了gbc.gridheight = 1添加后rightPanel_2。另外,您还设置了gbc.anchor价值CENTER and PAGE_END这会导致您的组件无法按您想要的方式堆叠。

我在代码中注释掉了应该删除的内容,并添加了上面解释的修复布局的代码:

public class HomeTopPanel extends JPanel {

    // BUTTONS
    private final JButton myAccountButton = new JButton("My Account");
    private final JButton updatePhoto = new JButton("Update Photo");

    // PANELS
    private final JPanel rightPanel_1 = new JPanel(new GridBagLayout()) {

        public Dimension getPreferredSize() {

            return new Dimension(1000, 550);
        };
    };
    private final JPanel rightPanel_2 = new JPanel(new GridBagLayout()) {

        public Dimension getPreferredSize() {

            return new Dimension(800, 300);
        };
    };
    private final JPanel logHistoryPanel = new JPanel(new GridBagLayout());

    // BORDERS
    private final Border homeTopPanel_LineBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
    private final Border rightPanel1_LineBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
    private final Border rightPanel2_LineBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
    private final TitledBorder logHistoryPanel_TitledBorder = BorderFactory.createTitledBorder("Log History");

    // LABELS
    private final JLabel imageContainer = new JLabel("User Image");

    // CONSTRAINTS
    GridBagConstraints gbc = new GridBagConstraints();

    // CONSTRUCTOR
    public HomeTopPanel() {

        // METHOD CALLS
        this.setLayout(new GridBagLayout()); // setting of layout should ALWAYS come first before adding constraints and components
        constructMyAccountButton();
        constructRightPanel_1();
        constructRightPanel_2();
        constructLeftPanelComponents();
        setRightPanelBorders();
    }

    public final void constructMyAccountButton() {

        gbc.anchor = GridBagConstraints.PAGE_START;
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.gridx = 0;
        gbc.gridy = 0;
        this.add(myAccountButton, gbc);
    }

    public final void constructRightPanel_1() {

        rightPanel_1.setBackground(Color.RED);
//      rightPanel_1.setPreferredSize(new Dimension(1000, 550));
        gbc.fill = GridBagConstraints.BOTH; // Optional: used for the 2 right panels
        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.gridx = 1;
        gbc.gridy = 0;
        this.add(rightPanel_1, gbc);
    }

    public final void constructRightPanel_2() {

        rightPanel_2.setBackground(Color.BLUE);
//      rightPanel_2.setPreferredSize(new Dimension(800, 300));
        gbc.gridheight = 3;
        rightPanel_1.add(rightPanel_2, gbc);
    }

    public final void constructLeftPanelComponents() {

        gbc.fill = GridBagConstraints.NONE; // Remove if you didn't use it above
        gbc.weightx = 0;
        gbc.weighty = 0;
        gbc.gridheight = 1;
        gbc.gridx = 0;
        gbc.gridy = 0;
//      gbc.ipadx = 0;
//      gbc.anchor = GridBagConstraints.PAGE_START;
        rightPanel_1.add(imageContainer, gbc);
        gbc.gridx = 0;
        gbc.gridy = 1;
//      gbc.anchor = GridBagConstraints.CENTER;
        rightPanel_1.add(updatePhoto, gbc);
        gbc.gridx = 0;
        gbc.gridy = 2;
//      gbc.anchor = GridBagConstraints.PAGE_END;
        logHistoryPanel.setPreferredSize(new Dimension(110, 100));
        rightPanel_1.add(logHistoryPanel, gbc);
    }

    private void setRightPanelBorders() {

        rightPanel_1.setBorder(rightPanel1_LineBorder);
        rightPanel_2.setBorder(rightPanel2_LineBorder);
        logHistoryPanel.setBorder(logHistoryPanel_TitledBorder);
        this.setBorder(homeTopPanel_LineBorder);
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        frame.add(new HomeTopPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

(已编辑)有关您使用的注释GridBagLayout:

  • @Override getPreferredSize()而不是打电话setPreferredSize(...). See here https://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi and here https://stackoverflow.com/questions/10866762/use-of-overriding-getpreferredsize-instead-of-using-setpreferredsize-for-fix.

  • 我建议使用新的GridBagConstraints对于每个新容器(如果不是每个新组件),否则您将面临一些令人讨厌的错误的风险,就像您所拥有的那样。教程还提到:

    正如您可能从上面的示例中猜到的那样,可以重用相同的内容GridBagConstraints多个组件的实例,即使组件具有不同的约束。但建议不要重复使用GridBagConstraints,因为如果您忘记为每个新实例重置字段,这很容易导致您引入微妙的错误。

    当您设置一个GridBagConstraints财产,它保留直至更改。设置gridheight在某些时候变为 1 会影响all add设置后调用,因此无需为每次调用再次将其设置为相同的值。这也适用于gridx你设置为0每次——实际上一次就足够了。我保留所有冗余调用的原因是,有时在添加组件之前更容易看到确切的位置,而不是搜索上次设置属性的代码。

  • 在生产阶段为组件着色有助于了解 GUI 的真实外观。

编辑:关于您的通用代码的注释

  • 在 EDT 上启动 GUI(请参阅Swing 中的并发 http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html):

    public static void main(String[] args) {
    
        SwingUtilities.invokeLater(() -> {
    
            JFrame frame = new JFrame();
            frame.add(new HomeTopPanel());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
        });
    }
    
  • 根据Java命名约定,变量名不应使用下划线(_)除非它们是常数。所以rightPanel_1应该rightPanel1.

  • 您正在创建 3 次相同的边框,BorderFactory.createLineBorder(Color.BLACK, 1);当局部变量可以使用时,您也可以将它们保留为字段。您甚至可以只在内部创建边框setBorder(...) call.

  • 我认为,您可以在配置每个组件的位置设置其边框,而不是将所有边框设置在一处。在代码中,您划分了方法来匹配组件,因此在该方法中完全配置组件是有意义的。

  • 将长方法分割成更小的方法final方法是处理可读性的绝佳方法。我希望我看到的不仅仅是 100 行组件初始化。但是,就像您的情况一样,如果您有一个共享对象(例如GridBagConstraints)那么你必须小心它在方法之间如何变化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GridBagLayout 如何将组件向北推 的相关文章

随机推荐