Swing GroupLayout:调整大小和限制组件大小

12

我正在使用GroupLayout来管理某些动态生成的数据输入表单中的组件。布局大致如下:

*-----------------------------------------------*
| label A     |   field A                       | 
| label B     |   field B                       |
| label C     |   field C                       |
*-----------------------------------------------*

我在水平布局中使用了2个并行组,并在垂直布局中使用了单个顺序组。大部分情况下,一切都正常。

我希望限制标签(这些标签只是JLabel的实例)的最大宽度为父JFrame宽度的1/3。如果JFrame是固定大小的,那么这很容易解决,但我必须处理它被调整大小的情况。

我从JFrame中获取ComponentListener.componentResized()事件,但一旦收到此类事件,我就有点卡住了。

我尝试过以下方法,但没有成功:

public void componentResized(ComponentEvent e) {
    int maxW = parentFrame.getWidth() / 3;
    for (JLabel l : labels) {
        l.setMaximumSize( // have also tried setSize() and setPreferredSize()
            new Dimension(
                Math.min(l.getSize().width, maxW),
                l.getMaximumSize().height));
    }
    groupLayout.invalidateLayout(getContentSpace());
}
有人能建议一种限制标签宽度的方法吗?

我可能可以每次从头开始重建布局,但感觉应该有更简单的方法。


永远不要使用setXXSize:https://dev59.com/questions/BGw05IYBdhLWcg3weBlF - kleopatra
标签增长超过最大标签的首选大小有什么原因吗? - trashgod
@trashgod 没有这个选项。我想要设置标签宽度的上限,而不是最小值。已经编辑了问题以使其更清晰。 - vaughandroid
1个回答

31
在这个例子中,GroupLayout可以简单地依赖于标签的首选大小,而不必诉诸于任何setXXXSize()方法。在这种方法中,
  • 标签的空间总是容纳最大的标签。
  • 文本字段以有用的方式可调整大小。
  • 结果在平台和字体上都正确。
  • "对于大多数组件,您不需要指定任何内容……因为组件本身具有所需的默认调整大小行为。"——如何使用GroupLayout:组件大小和可调整大小性
使用GroupLayout.Alignment.TRAILING将标签右对齐是一种个人偏好,并且我添加了第二个面板以显示它嵌套在另一个布局中的工作原理。

enter image description here

import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

/** @see https://dev59.com/omoy5IYBdhLWcg3wg-cm */
public class GroupPanel extends JPanel {

    private JLabel label1 = new JLabel("Primary:");
    private JTextField field1 = new JTextField(16);
    private JLabel label2 = new JLabel("Secondary:");
    private JTextField field2 = new JTextField(16);
    private JLabel label3 = new JLabel("Tertiary:");
    private JTextField field3 = new JTextField(16);

    public GroupPanel(int n) {
        this.setBorder(BorderFactory.createTitledBorder("Panel " + n));
        GroupLayout layout = new GroupLayout(this);          
        this.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        layout.setHorizontalGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                .addComponent(label1)
                .addComponent(label2)
                .addComponent(label3))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(field1)
                .addComponent(field2)
                .addComponent(field3))
        );
        layout.setVerticalGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(label1)
                .addComponent(field1))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(label2)
                .addComponent(field2))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(label3)
                .addComponent(field3))
        );
    }

    private static void display() {
        JFrame f = new JFrame("GroupPanel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS));
        f.add(new GroupPanel(1));
        f.add(new GroupPanel(2));
        f.add(Box.createVerticalGlue());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                display();
            }
        });
    }
}

这是一个非常清晰的例子,感谢您提供。您提供的代码几乎与我已经实现的代码完全相同,但关键部分是“大多数组件不需要指定任何内容...因为组件本身具有所需的默认调整大小行为。” 我想我的标签需要自定义实现,覆盖getPreferredSize()方法。 - vaughandroid
很好;还可以参考这个(不太灵活的)示例 - trashgod
1
请参考这个(更加灵活的)示例 - trashgod
我在使用GroupLayout之间隔了五年,所以我不得不再次参考@trashgod的上面的示例。这是一个很好的方式来刷新我对如何使用该布局的记忆。太棒了! - Sheldon R.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接