繁体   English   中英

如何使用 GridLayout 设置组件大小? 有更好的方法吗?

[英]How to set the component size with GridLayout? Is there a better way?

我正在用 Java 开发一个更大的 GUI,我对布局管理器很生气。

我有一个“设置面板”,其中包含可变数量的 JComponent(标签、按钮、JSpinner、JSlider 等)。 我只想要以下内容:

JLabel <-> JComponent

JLabel <-> JComponent

JLabel <-> JComponent

...

我的面板大小为 500px,这样就有足够的空间容纳很多组件。 不幸的是 GridLayout 总是将组件的大小拉伸到整个面板,即使我为每个组件设置了 MaximumSize。 如果只有两个按钮,每个按钮的高度为 250 像素,这看起来很愚蠢。

我尝试了流布局,但我无法找到正确制作新线条的方法。 我试过BoxLayout.Y_AXIS,但是Components总是居中,Label和Component不在同一行。

有没有人知道 LayoutManagers 正确处理这个问题的好方法?

其他布局的替代方案可能是将带有 GridLayout 的面板放在另一个 FlowLayout 面板中。 这样,您的间距将保持不变,但不会扩展到整个可用空间。

不要将 GridLayout 用于它不应该做的事情。 在我看来,GridBagLayout 更适合您,无论是它还是 MigLayout(尽管您必须先下载它,因为它不是标准 Java 的一部分)。 或者组合布局管理器,例如用于行的 BoxLayout 和用于保存所有行的 GridLayout。

例如,使用 GridBagLayout:

import java.awt.*;
import javax.swing.*;

public class LayoutEg1 extends JPanel{
    private static final int ROWS = 10;

    public LayoutEg1() {
        setLayout(new GridBagLayout());
        for (int i = 0; i < ROWS; i++) {
            GridBagConstraints gbc = makeGbc(0, i);
            JLabel label = new JLabel("Row Label " + (i + 1));
            add(label, gbc);

            JPanel panel = new JPanel();
            panel.add(new JCheckBox("check box"));
            panel.add(new JTextField(10));
            panel.add(new JButton("Button"));
            panel.setBorder(BorderFactory.createEtchedBorder());
            gbc = makeGbc(1, i);
            add(panel, gbc);
        }
    }

    private GridBagConstraints makeGbc(int x, int y) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = 1;
        gbc.gridheight = 1;
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.weightx = x;
        gbc.weighty = 1.0;
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.anchor = (x == 0) ? GridBagConstraints.LINE_START : GridBagConstraints.LINE_END;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        return gbc;
    }

    private static void createAndShowUI() {
        JFrame frame = new JFrame("Layout Eg1");
        frame.getContentPane().add(new LayoutEg1());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}

在我的项目中,我设法使用 GridLayout 并且结果非常稳定,没有闪烁,并且垂直滚动条工作正常。

首先,我为设置创建了一个 JPanel; 在我的情况下,它是一个网格,每个参数一行和两列:左列用于标签,右列用于组件。 我相信你的情况是相似的。

JPanel yourSettingsPanel = new JPanel();
yourSettingsPanel.setLayout(new GridLayout(numberOfParams, 2));

然后我通过迭代我的参数并在添加 JLabel 和添加组件之间交替来填充这个面板。

for (int i = 0; i < numberOfParams; ++i) {
    yourSettingsPanel.add(labels[i]);
    yourSettingsPanel.add(components[i]);
}

为了防止 yourSettingsPanel 扩展到整个容器,我首先将它包裹在一个虚拟面板的北部区域,我称之为 northOnlyPanel。

JPanel northOnlyPanel = new JPanel();
northOnlyPanel.setLayout(new BorderLayout());
northOnlyPanel.add(yourSettingsPanel, BorderLayout.NORTH);

最后,我将 northOnlyPanel 包装在 JScrollPane 中,它在任何地方都应该表现良好。

JScrollPane scroll = new JScrollPane(northOnlyPanel,
                                     JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                                     JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

您很可能希望在 JFrame 中显示此扩展的 JScrollPane; 您可以将它添加到一个 BorderLayout JFrame,在 CENTER 区域:

window.add(scroll, BorderLayout.CENTER);

就我而言,我将它放在 GridLayout(1, 2) 面板的左列,并使用右列显示每个参数的上下文帮助。

JTextArea help = new JTextArea();
help.setLineWrap(true);
help.setWrapStyleWord(true);
help.setEditable(false);

JPanel split = new JPanel();
split.setLayout(new GridLayout(1, 2));
split.add(scroll);
split.add(help);

对于更复杂的布局,我经常使用GridBagLayout ,它更复杂,但这就是代价。 今天,我可能会查看MiGLayout

您需要尝试以下方法之一:

  1. 网格包布局
  2. 迁移布局
  3. 弹簧布局

它们提供了更多功能,并且更容易获得您正在寻找的内容。

我改用了WrapFlowLayout

JPanel yourPanel = new JPanel(new WrapFlowLayout(10, 10);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM