我试图建立一个相当基本的面板来添加/编辑数据库中的用户。为了实现这一点,我想在左侧为不同的字段添加一些标签,在右侧为该字段设置适当的控件。 (所以,左边可能会说"用户名","用户类型","到期日期"等等,相关的右侧将有一个文本面板,下拉列表和日历小部件。)
我遇到的问题是我希望这些都是水平排列的(一个标签和它相关的"控制区域"应该从同一行开始),以及垂直(所有标签应沿同一垂直线开始,所有控制区域应从同一垂直线开始。)但是,某些控制区域比其他区域更大或更小;许多只包含一个文本面板,而另一些则包含与它们相关的单选按钮,日历小部件等。
此外,所需的字段类型经常变化,并且根据上下文(例如是否正在创建新用户或编辑旧用户以及控制用户的权限级别),其中一些字段可能是排除。所以,我想要的东西会在很大程度上自我安排 - 如果我必须非常手动设置位置,我预计事情会因为部分被排除而中断。
我希望看到的是一个布局管理器,它基本上可以让我在灵活的网格上设置坐标,然后自动调整网格大小以为每个元素提供最小的空间,同时仍保持网格线笔直。这样我就可以简单地保留一个控件列表及其相关标签,并以编程方式构建面板,以便始终将标签/控件分配给相同的行。
我还没有想到如何与任何布局管理员一起做到这一点:GridLayout
似乎要求所有内容都相同,BoxLayout
想要垂直排列或横向但不是两者。所以,我一直发现我的行排成一行但没有整齐地垂直对齐,或者错误的标签与错误的控件对齐。
有什么建议吗?
答案 0 :(得分:3)
GridBagLayout
是实现这一目标的最简单方法。它不是最直观的布局管理器:您需要指定一个约束'添加时为每个组件添加。有一些方法可以指定相对于前一个组件的位置,但我倾向于使用显式gridx
和gridy
值来确保您确切了解事情的发展方向。您可以使用一个方法来添加标签和组件,然后移动到下一行,以便包含此逻辑:
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:
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