【问题标题】:How can I best lay out these components in Swing?如何在 Swing 中最好地布置这些组件?
【发布时间】:2010-09-30 12:08:33
【问题描述】:

对于需要显示图像中显示的组件的 JPanel,最好的方法/LayoutManager 是什么? (请注意,当窗口大小改变时,字段应该水平调整大小,而不是标签)。

我目前正在尝试(并且正在努力)使用 GridBagLayout 来实现。这是正确的方法还是有更好的方法?我应该尝试划分 + 征服单独的部分吗?

任何想法或建议将不胜感激。 :-)

http://img261.imageshack.us/img261/2091/layouthb6.png

PS 如果你看到这里没有图片,请耐心等待我修复它!

【问题讨论】:

    标签: java swing layout


    【解决方案1】:

    我会看看嵌套JPanels。将每一行设为单独的JPanel,然后将JPanels 堆叠起来非常容易。

    否则您可以使用GridBagLayout。这是我用来更好地控制组件放置位置的方法。

    使用GridBagLayout,您可以通过递增GridBagConstraint.gridx 然后重置GridBagConstraint.gridx = 0GridBagConstraint.gridy++ 以移动到下一行来布局行。

    【讨论】:

    • 是的,这很适合网格袋。 JGoodies formlayout 可以,但我有一些“不确定”的结果,尤其是在大小或控件动态变化的情况下。
    • GridBagLayout 万岁! \o/ 不过,我更喜欢在添加新组件时使用完整的 GridBagConstraints 构造函数。这样可以更轻松地在现有组件之间插入其他组件,而不必担心约束对象中的“剩余”。
    • 我认为约束在大多数情况下都可以很好地使用默认值。只需更改 gridx/y 和 gridheight/width 即可。
    【解决方案2】:

    我建议使用第三方免费布局管理器。我想到了MigLayout(查看链接页面底部的示例表单)或JGoodies FormLayout,它特别擅长此类表单。

    标准布局管理器很不错,但对于经常用于此类屏幕(Netbeans 中的 Matisse 设计师使用的新 GroupLayout 并不是白费的)来说,完全不够。链接布局管理器更易于使用和维护恕我直言。

    【讨论】:

    • 我从未听说过 MigLayout,但它看起来很棒!我现在一定要试一试。
    • 当 GridBagLayout 完全有能力解决这个问题时,我不会真正引入第三方布局管理器。
    【解决方案3】:

    我肯定会使用DesignGridLayout:

    DesignGridLayout layout = new DesignGridLayout(this);
    layout.row().grid(label0).add(field0);
    layout.emptyRow();
    layout.row().grid(label1).add(field1);
    layout.row().grid(label2).add(field2);
    layout.row().grid(label3).add(field3);
    layout.row().grid(label4).add(field4);
    layout.emptyRow();
    layout.row().grid(label5).add(field5).grid(label6).add(field6);
    layout.row().grid(label7).add(field7).grid(label8).add(field8);
    layout.emptyRow();
    layout.row().grid(label9).add(field9);
    

    免责声明:我是 DesignGridLayout 的作者之一。

    【讨论】:

      【解决方案4】:

      如果您可以使用外部代码,请查看JGoodies 布局管理器。

      就我个人而言,我发现 GridBagLayout 带来的麻烦多于它的价值——在某种程度上,我已经编写了自己的布局管理器来避免它。

      【讨论】:

        【解决方案5】:

        我个人更喜欢GroupLayout

        即使您不使用 GUI 构建器,您也可以手动使用布局,如果您了解这些概念,使用起来相当简单直接。

        【讨论】:

          【解决方案6】:

          TableLayout 是我的选择,您可以使用 TableLayout.FILL 等常量来自动调整大小并指定固定像素宽度。

          TableLayout

          【讨论】:

            【解决方案7】:

            您的布局看起来基本上是由“线条”组成的。所以就个人而言,我会:

            • 使用 Box.createVerticalBox() 创建一个垂直框;这将垂直堆叠其组件 - 实际上,让您添加线条
            • 为每一行创建一个面板:我认为您可以使用带有 BorderLayout 的 JPanel(以及左侧的标签,文本字段作为中心组件),或者再次使用 Box.createHorizo​​ntalBox(),并添加标签和文本字段,具有适当的最小/首选大小
            • 您可以在需要行分隔符的垂直框中添加“支柱”
            • 您的带有两组标签/字段的行需要一些特殊处理,但它本质上只是一个水平框,里面有两条“行”。

            就个人而言,我从不使用驳船杆接触 GridBagLayout。也许只有我一个人,但我发现并发算法和机器代码编程比理解 GridBagLayout 更容易......

            【讨论】:

            • 谢谢,不过我觉得这样会有标签不能自动垂直对齐的问题......?
            • 您可以将标签设置为固定大小。
            • Neil,GridBagLayout 并不难使用。我遇到过几次 GridBagLayout 比任何其他 LayoutManager 组合更容易实现的情况。好的,GridBagConstraints 构造函数令人生畏,但你知道,强大的力量,巨大的责任和东西。 :)
            【解决方案8】:

            在 Netbeans 推出他们的 gui builder 之前,我曾经非常讨厌做 swing 布局。你可以在这里看到一个演示。 http://rghosting.co.cc

            【讨论】:

              【解决方案9】:

              从 Java SE 6 开始,您可以使用 GroupLayout

              这很简单,看起来就像你想要的那样。

              对于这个窗口:

              alt text http://img165.imageshack.us/img165/8237/sampleusinggrouplayoutca2.png

              我有这个代码:

                  // Layout the components using the new GroupLayout added
                  // in java 1.6.
                  // Adding to the main frame
                  private void layoutComponents(){
                      JPanel panel = new JPanel();
              
                      GroupLayout layout = new GroupLayout(panel);
                      panel.setLayout(layout);
              
                      layout.setAutoCreateGaps(true);         
                      layout.setAutoCreateContainerGaps(true);
              
                      SequentialGroup hGroup = layout.createSequentialGroup();
              
                      JLabel nameLbl  = new JLabel("Name");
                      JLabel countLbl = new JLabel("Amount");
                      JLabel dateLbl  = new JLabel("Date(dd/MM/yy)");
                      hGroup.addGroup(layout.createParallelGroup().
                              addComponent(nameLbl).
                              addComponent(countLbl).
                              addComponent(dateLbl).
                              addComponent(go));
              
                      hGroup.addGroup(layout.createParallelGroup().
                              addComponent(name).
                              addComponent(count).
                              addComponent(date));
              
                      layout.setHorizontalGroup(hGroup);
              
                      SequentialGroup vGroup = layout.createSequentialGroup();
              
                      vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                              addComponent(nameLbl).
                              addComponent(name));
              
                      vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                              addComponent(countLbl).
                              addComponent(count));
              
                      vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                              addComponent(dateLbl).
                              addComponent(date));
              
                      vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                              addComponent(go));
                      layout.setVerticalGroup(vGroup);
              
                      frame.add( panel , BorderLayout.NORTH );
                      frame.add( new JScrollPane( textArea ) );
                  }
              

              【讨论】:

                【解决方案10】:

                GridBagLayout 绝对是最好的选择。而NetBeans Matisse 可能是实现这一目标的最快方法。如果您使用的是其他 IDE,只需复制并粘贴自动生成的代码即可。

                【讨论】:

                  【解决方案11】:

                  GridBagLayout,当然。

                  如果表单就是这样,那么您确实需要多个JPanel。 (如果你有按钮,你可能还需要一个,这取决于它们的位置/方式)

                  字段 0 - 4 和 9 将 gridwidth 设置为 4,其他为默认值(1,但您无需将其设置为 1)

                  字段组之间的“空格”可以通过插入来实现。

                  (至少对于这种布局)我不建议使用第三方布局管理器。 GridBagLayout 并不复杂。只是需要(一点点)时间来适应它。

                  Visual Editor + Eclipse 可以轻松为您完成这些工作。 (我对 Netbeans 及其 Swing 开发不是很满意。尝试过,但从未爱上。可能是我太沉迷于 Eclipse)

                  【讨论】:

                    【解决方案12】:

                    我认为,在所有标准布局中,GridBagLayout 应该最适合您的需求。

                    您可以尝试以下示例,其中我使用 addToLayout 将复杂的 GridBagConstraints 构造函数简化为我真正需要的。

                    如果您可以使用 IDE,这确实可以让事情变得更容易(例如 NetBeans 中的 Matisse)。

                    import java.awt.GridBagConstraints;
                    import java.awt.GridBagLayout;
                    
                    import javax.swing.JFrame;
                    import javax.swing.JLabel;
                    import javax.swing.JPanel;
                    import javax.swing.JTextField;
                    
                    public class GridBagLayoutTest extends JPanel {
                    
                        public GridBagLayoutTest() {
                            setLayout(new GridBagLayout());
                            addToLayout(new JLabel(     "Label 0" ), 0, 0, 0d, 1);
                            addToLayout(new JTextField( "Field 0" ), 0, 1, 1d, 4);
                            addToLayout(new JLabel(     "*"       ), 0, 5, 0d, 1);
                            addToLayout(new JPanel()               , 1, 0, 0d, 1);
                            addToLayout(new JLabel(     "Label 1" ), 2, 0, 0d, 1);
                            addToLayout(new JTextField( "Field 1" ), 2, 1, 1d, 4);
                            addToLayout(new JLabel(     "*"       ), 2, 5, 0d, 1);
                            addToLayout(new JLabel(     "Label 2" ), 3, 0, 0d, 1);
                            addToLayout(new JTextField( "Field 2" ), 3, 1, 1d, 1);
                            addToLayout(new JLabel(     "*"       ), 3, 2, 0d, 1);
                            addToLayout(new JLabel(     "Label 3" ), 3, 3, 0d, 1);
                            addToLayout(new JTextField( "Field 3" ), 3, 4, 1d, 1);
                            addToLayout(new JLabel(     "*"       ), 3, 5, 0d, 1);
                        }
                    
                        private void addToLayout(java.awt.Component comp, int y, int x, double weightx, int gridwidth) {
                            add(comp, new GridBagConstraints(x, y, gridwidth, 1, weightx, 0d,
                                                             GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                                                             new java.awt.Insets(2, 4, 2, 4), 0, 0 ) );
                        }
                    
                        public static void main(String[] args) {
                            JFrame frame = new JFrame();
                            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                            frame.getContentPane().add(new GridBagLayoutTest());
                            frame.setSize(800, 600);
                            frame.setVisible(true);
                        }
                    }
                    

                    【讨论】:

                      【解决方案13】:

                      您可以将布局描述为 HTML 表格,然后使用此工具: http://www.onyxbits.de/content/blog/patrick/java-gui-building-gridbaglayout-manager-made-easy

                      将布局转换为 Java 代码以配置 GridBagLayout。

                      【讨论】:

                        猜你喜欢
                        • 2013-10-12
                        • 2013-06-27
                        • 2011-10-31
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2019-12-05
                        • 2010-10-17
                        • 2020-08-24
                        相关资源
                        最近更新 更多