GridBag布局如何将组件向北推 [英] GridBag Layout How to push components north

查看:90
本文介绍了GridBag布局如何将组件向北推的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码

 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);
}
}   

这就是我得到的:

我有2个问题:

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

我想做到这一点:

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

then push it to top. I tried using insets and weight but still can't get the result I desire.

我将不胜感激.在这一点上,我不知道这是ipadx/ipady还是weightx/weighty的问题.

I'd appreciate any help. At this point, I don't know if it's a problem with ipadx/ipady or weightx / weighty.

推荐答案

  1. 如何将所有这四个对象推到顶部?

您需要为以下组件分配权重:gbc.weightxgbc.weighty.

You need to assign weights to the components: gbc.weightx and gbc.weighty.

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

您添加rightPanel_2后忘记重设gbc.gridheight = 1.另外,将gbc.anchor值设置为CENTERPAGE_END,这将导致组件无法按需堆叠.

You forgot to reset gbc.gridheight = 1 after adding rightPanel_2. Also, you set the gbc.anchor value to CENTER and PAGE_END which causes your components to not stack as you want.

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

I commented out in your code things which should be removed and added the code I explained above that fixes the layout:

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用法的说明:

(Edited) Notes on your usage of GridBagLayout:

  • @Override getPreferredSize()而不是调用setPreferredSize(...).请参见此处此处.

  • @Override getPreferredSize() instead of calling setPreferredSize(...). See here and here.

我建议为每个新容器(如果不是每个新组件)使用一个新的GridBagConstraints,否则您将冒一些讨厌的错误,例如所遇到的错误.本教程还提到:

I would recommend using a new GridBagConstraints for each new container (if not each new component), otherwise you are risking some nasty bugs like the ones you have. The tutorial also mentions:

从上面的示例中您可能已经猜到了

,即使多个组件具有不同的约束,也可以将相同的GridBagConstraints实例重用于多个组件.但是,建议您不要重复使用GridBagConstraints,因为如果您忘记为每个新实例重置字段,很容易导致引入细微的错误.

As you might have guessed from the above example, it is possible to reuse the same GridBagConstraints instance for multiple components, even if the components have different constraints. However, it is recommended that you do not reuse GridBagConstraints, as this can very easily lead to you introducing subtle bugs if you forget to reset the fields for each new instance.

设置GridBagConstraints属性后,该属性会一直保留直到更改.将gridheight设置为1将在设置后影响 all add调用,因此无需为每次调用将其再次设置为相同的值.每次将gridx设置为0时也是如此-实际上一次就足够了.我离开所有冗余调用的原因是,有时在添加组件之前更容易查看确切位置,而不是在上次设置属性时搜索代码.

When you set a GridBagConstraints property, it remains until changed. Setting the gridheight to 1 at some point will affect all add invocations after setting it, so there is no need to set it again to the same value for each invocation. This is also true for gridx which you set to 0 each time - once is actually enough. The reason I left all of the redundant calls is that it is sometimes easier to see the exact location before adding the component instead of searching the code for the last time the property was set.

在生产阶段为组件着色有助于了解GUI的外观.

Coloring components during production phase helps to see how the GUI really looks.

关于通用代码的注释

  • 在EDT上启动GUI(请参阅摆动):

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.

  • According to Java naming conventions, variables names should not use underscores (_) unless they are constants. So rightPanel_1 should be rightPanel1.

    您正在创建3倍相同的边框,BorderFactory.createLineBorder(Color.BLACK, 1);,并且在局部变量可用时也将其保留为字段.您甚至可以在setBorder(...)调用内创建边框.

    You are creating 3 times the same border, BorderFactory.createLineBorder(Color.BLACK, 1); and you are also keeping them as fields when local variables will do. You can even just create the border inside the setBorder(...) call.

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

    I think that instead of setting all the borders in one place, you can set each component's border where you configure it. In your code you divided your methods to match components, so it makes sense to fully configure the component in that method.

    将长方法拆分为较小的final方法是处理可读性的一种极好方法.我希望我能看到更多而不是100行的组件初始化.但是,就像您的情况一样,如果您有一个共享库(例如GridBagConstraints),则必须注意它在方法之间的变化.

    Splitting a long method into smaller final methods is an excellent way to deal with readability. I wish I saw it more rather than 100 lines of components initializations. However, as in your case, if you have a shared object (like GridBagConstraints) then you have to be careful how it changes between the methods.

    这篇关于GridBag布局如何将组件向北推的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆