布局管理器,用于垂直和水平排列不同大小的组件

时间:2016-08-29 22:29:04

标签: java swing user-interface layout jpanel

我试图建立一个相当基本的面板来添加/编辑数据库中的用户。为了实现这一点,我想在左侧为不同的字段添加一些标签,在右侧为该字段设置适当的控件。 (所以,左边可能会说"用户名","用户类型","到期日期"等等,相关的右侧将有一个文本面板,下拉列表和日历小部件。)

我遇到的问题是我希望这些都是水平排列的(一个标签和它相关的"控制区域"应该从同一行开始),以及垂直(所有标签应沿同一垂直线开始,所有控制区域应从同一垂直线开始。)但是,某些控制区域比其他区域更大或更小;许多只包含一个文本面板,而另一些则包含与它们相关的单选按钮,日历小部件等。

此外,所需的字段类型经常变化,并且根据上下文(例如是否正在创建新用户或编辑旧用户以及控制用户的权限级别),其中一些字段可能是排除。所以,我想要的东西会在很大程度上自我安排 - 如果我必须非常手动设置位置,我预计事情会因为部分被排除而中断。

我希望看到的是一个布局管理器,它基本上可以让我在灵活的网格上设置坐标,然后自动调整网格大小以为每个元素提供最小的空间,同时仍保持网格线笔直。这样我就可以简单地保留一个控件列表及其相关标签,并以编程方式构建面板,以便始终将标签/控件分配给相同的行。

我还没有想到如何与任何布局管理员一起做到这一点:GridLayout似乎要求所有内容都相同,BoxLayout想要垂直排列或横向但不是两者。所以,我一直发现我的行排成一行但没有整齐地垂直对齐,或者错误的标签与错误的控件对齐。

有什么建议吗?

2 个答案:

答案 0 :(得分:3)

GridBagLayout是实现这一目标的最简单方法。它不是最直观的布局管理器:您需要指定一个约束'添加时为每个组件添加。有一些方法可以指定相对于前一个组件的位置,但我倾向于使用显式gridxgridy值来确保您确切了解事情的发展方向。您可以使用一个方法来添加标签和组件,然后移动到下一行,以便包含此逻辑:

private final JPanel pane = new JPanel(new GridBagLayout());
private final GridBagConstraints c = new GridBagConstraints();

private void addLabelledComponent(String label, Component component) {
    c.gridx = 0;
    pane.add(new JLabel(label), c);
    c.gridx = 1;
    pane.add(component, c);
    c.gridy++;
}

有关详细信息,请参阅How To Use GridBagLayout,例如定义对齐,填充,跨越行和列等。

答案 1 :(得分:3)

Here's an example, as you can see, there are 2 normal sized rows, 1 medium sized and 1 larger (taller) row in different order, I think this is something similar to what you wanted to do

The height of the row is determined by the ipady attribute of the GridBagConstraints, you can read more on How to use GridBagLayout and the docs

I haven't used GridBagLayout a lot, so there might be some things that could be skipped or improved, but for a matter of having this example, here's the output of the code below:

enter image description here

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class GridBagLayoutExample {
    private JPanel contentPane;
    private JFrame frame;
    private JLabel label;
    private JTextField field;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new GridBagLayoutExample().createAndShowGui();
            }
        });
    }

    public void createAndShowGui() {
        frame = new JFrame("GridBagLayout Example");
        contentPane = new JPanel();
        contentPane.setLayout(new GridBagLayout());

        GridBagConstraints c = new GridBagConstraints();

        label = new JLabel("A small label");
        field = new JTextField();

        c.insets = new Insets(0, 10, 0, 10);
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0;
        c.gridx = 0;
        c.gridy = 0;
        contentPane.add(label, c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 2;
        c.gridy = 0;
        c.gridwidth = 2;
        contentPane.add(field, c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 1;
        c.ipady = 20;
        contentPane.add(new JLabel("Another but much larger JLabel"), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 2;
        c.gridy = 1;
        c.ipady = 20;
        c.gridwidth = 2;
        contentPane.add(new JButton("And including a larger JButton"), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 2;
        c.ipady = 60;
        contentPane.add(new JLabel("A TALLER ROW!"), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 2;
        c.gridy = 2;
        c.ipady = 60;
        c.gridwidth = 2;
        contentPane.add(new JTextField(), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 3;
        c.ipady = 0;
        contentPane.add(new JLabel("Another normal row"), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 2;
        c.gridy = 3;
        c.gridwidth = 2;
        contentPane.add(new JTextField(), c);

        frame.add(contentPane);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

I hope you have an idea with this in mind now, if you still have doubts, ask another (more specific) question including your mcve