【问题标题】:Gridbag layout -> how to stop components from resizing along with the window?Gridbaglayout -> 如何阻止组件与窗口一起调整大小?
【发布时间】:2014-10-01 00:40:29
【问题描述】:

我在 NetBeans 8 / Java 7 中有一个 JFframe 表单。

它有一堆标签、文本框、下拉菜单等。 这些是左侧尺寸的一列,全部堆叠在一起。

截图如下:

如何防止所有这些组件粘在右侧并与窗口一起调整大小,同时让最右侧的预览框也随之调整大小?

我是 Java 新手,我发现 gridbaglayout 是唯一能正确对齐所有内容的工具。我只希望左侧的组件很好地对齐而不是四处移动。我只希望右侧面板根据窗口大小调整大小。

谢谢,

【问题讨论】:

    标签: java swing resize layout-manager gridbaglayout


    【解决方案1】:

    我只希望右侧面板根据窗口大小调整大小。

    默认情况下,每行中的所有列都以相等的百分比划分。

    要强制第二列(右侧)占用更多空间,请使用GridBagConstraints#weightx 为其分配更高的百分比

    gc.weightx = 0.75; // 75%
    

    不要忘记使用GridBagConstraints#fill完全填充水平空间

    gc.fill = GridBagConstraints.HORIZONTAL;
    

    如果您希望第一列的宽度固定,则通过覆盖 getPreferredSize() 方法设置左侧面板的首选尺寸,并将 100% 的宽度分配给右侧面板。

    JPanel leftSidePanel = new JPanel() {
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(..., ...);
        }
    }
    

    看看我的另一篇帖子GridBagLayout: How to set fixed column width? 解释得更好。

    值得在Solving Common Layout Problems上阅读 Swing 教程

    【讨论】:

    • 似乎 NetBeans 使 initComponents 代码变灰。我可能不得不切换到eclipse?
    【解决方案2】:

    您需要将填充约束设置为 NONE。

    教程:How to Use GridBagLayout

    当您将每个组件添加到面板时,它看起来像这样(来自教程):

    JPanel pane = new JPanel(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    
    //For each component to be added to this container:
    //...Create the component...
    //...Set instance variables in the GridBagConstraints instance...
    pane.add(theComponent, c);
    

    你需要确保你打电话:

    c.fill = GridBagConstraints.NONE;
    

    对于您添加到面板且不想水平拉伸的每个组件的每个约束对象。

    如果您要为每个组件重复使用相同的约束对象,如果这是您想要的结果,您可以简单地设置一次。

    编辑:

    正如其他一些人指出的那样,OP 可能希望字段伸展,但只能达到一定的限制(目前尚不清楚)。在这种情况下,您将使用

    的组合
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 0;
    

    正如已经指出的那样。示例:

    import java.awt.*;
    import javax.swing.*;
    
    public class GridBagDemo implements Runnable
    {
      public static void main(String[] args)
      {
        SwingUtilities.invokeLater(new GridBagDemo());
      }
    
      public void run()
      {
        // 4 components that all have different widths
        JButton btnBrowse = new JButton("Browse");
        JTextField txfHeight = new JTextField(4);
        JTextField txfWidth = new JTextField(10);
        JButton btnMore = new JButton("More PDF Attributes");
    
        // the preview pane?
        JTextArea txaPreview = new JTextArea(8, 20);
        JScrollPane scrPreview = new JScrollPane(txaPreview);
        scrPreview.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    
        GridBagConstraints gbc = new GridBagConstraints();
        // we'll use these constraints for all components
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.insets = new Insets(2,4,2,4);
    
        JPanel panel = new JPanel(new GridBagLayout());
    
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.NONE;
        gbc.weightx = 0;
        panel.add(new JLabel("Source PDF size..."), gbc);
    
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 2;
        gbc.gridheight = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel.add(btnBrowse, gbc);
    
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.NONE;
        gbc.weightx = 0;
        panel.add(new JLabel("Height (in inches):"), gbc);
    
        gbc.gridx = 1;
        gbc.gridy = 2;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel.add(txfHeight, gbc);
    
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.NONE;
        gbc.weightx = 0;
        panel.add(new JLabel("Width (in inches):"), gbc);
    
        gbc.gridx = 1;
        gbc.gridy = 3;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel.add(txfWidth, gbc);
    
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.gridwidth = 2;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel.add(btnMore, gbc);
    
        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.gridwidth = 2;
        gbc.fill = GridBagConstraints.VERTICAL;
        gbc.weighty = 1;
        panel.add(Box.createVerticalGlue(), gbc);
    
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.NONE;
        gbc.weightx = 0;
        gbc.weighty = 0;
        panel.add(new JLabel("Preview"), gbc);
    
        gbc.gridx = 2;
        gbc.gridy = 1;
        gbc.gridwidth = 1;
        gbc.gridheight = 8; // some number that's > the number of entry rows
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1;
        gbc.weighty = 1;
        panel.add(scrPreview, gbc);
    
        JFrame frame = new JFrame("GrigBag Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JScrollPane(panel), BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    }
    

    【讨论】:

    • 这也会停止该列中的组件被调整为具有相同的大小。更可能的意图是使用 NONE 以外的填充值,但 weightx 为零以避免获得额外空间。
    • @Holger 你可能是对的(因为这也是我会做的 ;-),但由于 OP 没有提到这个要求(让他们填到右边,但最多最宽组件的宽度),我没有做任何假设。
    • 您好,感谢您的回答。我看不出如何在 NetBeans 中做到这一点。有什么想法吗?
    • IDE(在您的情况下为 Netbeans)的选择与您使用的 LayoutManager 的选择无关。或者您正在使用某种 GUI 构建器?如果你是的话,你应该在你的问题中提到这一点。
    • 抱歉,我的意思是 initComponents 方法在 NetBeans 中始终显示为灰色,因此无法更改代码。我尝试了 Pre Init 和 Post Init,但我的位置不正确。
    【解决方案3】:

    gridbaglayout 是我发现的唯一可以正确对齐所有内容的。

    MigLayout 经理可以轻松做到这一点。它还提供了更好的便携性。 注意相关间隙 (r)、对话框插入 (dialog) 和逻辑像素 (lp) 的使用。 这些单位相应地转换为像素。另一方面,GridbagLayout 直接以像素为单位设置空间,这是不够的,例如更改字体或分辨率 会影响布局。

    参见以下代码示例:

    package com.zetcode;
    
    import java.awt.EventQueue;
    import javax.swing.BorderFactory;
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JSeparator;
    import javax.swing.JTextField;
    import net.miginfocom.swing.MigLayout;
    
    
    public class MigLayoutPreview2 extends JFrame {
    
        public MigLayoutPreview2() {
    
            initUI();
    
            setTitle("Design preview");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setLocationRelativeTo(null);
        }
    
        private void initUI() {
    
            JPanel pnl = new JPanel(new MigLayout("ins dialog, wrap"));
    
            pnl.add(new JLabel("Source PDF file..."), "pad 0 -5lp 0 0");
            pnl.add(new JButton("Browse"), "growx");
            pnl.add(new JLabel("Height (inches):"), "sgx, split 2");
            pnl.add(new JTextField(10), "growx");
            pnl.add(new JLabel("Width (inches):"), "sgx, split 2");
            pnl.add(new JTextField(10), "growx"); 
            pnl.add(new JButton("More PDF attributes"), "growx");
            pnl.add(new JSeparator(), "pad 0 -5lp 0 0, gaptop r, growx");
            pnl.add(new JLabel("Set bounding box..."), "pad 0 -5lp 0 0");
            pnl.add(new JComboBox(), "growx");
            pnl.add(new JSeparator(), "pad 0 -5lp 0 0, gaptop r, growx");
            pnl.add(new JLabel("Sheet size..."), "pad 0 -5lp 0 0");
            pnl.add(new JComboBox(), "growx");
            pnl.add(new JLabel("Height (inches):"), "sgx, split 2");
            pnl.add(new JTextField(10), "growx");
            pnl.add(new JLabel("Width (inches):"), "sgx, split 2");
            pnl.add(new JTextField(10), "growx"); 
            pnl.add(new JSeparator(), "pad 0 -5lp 0 0, gaptop r, growx");
    
            JPanel rpnl = new JPanel();
            rpnl.setBorder(BorderFactory.createEtchedBorder());
    
            pnl.add(rpnl, "cell 2 0, w 90, spany, pushx, grow");
    
            add(pnl);
            pack();
        }
    
        public static void main(String[] args) {
    
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    MigLayoutPreview2 ex = new MigLayoutPreview2();
                    ex.setVisible(true);
                }
            });
        }
    }
    

    我已经复制了您的部分屏幕截图并保留了缩进。 水平分隔符不会完全伸展,因为我相信这不是 优化设计。通过消除巨大的空间也改进了设计 在标签和文本字段之间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      • 2018-06-25
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      相关资源
      最近更新 更多