与布局要求一样,任务是找到一个合适的 LayoutManager,然后让它完成工作:即弄清楚如何根据组件的可见性分配可用空间。有了这个,你的工作归结为切换可见性并向后倾斜。
大多数核心管理者只是忽略隐藏的组件(可能是也可能不是你想要的)。高级管理器可以进行全方位配置——从与可见组件完全相同的方式处理到忽略。Fi MigLayout(我个人目前最喜欢的),具有 4 个级别的隐藏模式(相同方式,将组件大小设置为 0,0,将组件大小设置为 0,0,周围的所有间隙都为零,完全忽略)
下面是一个简单的示例:尝试隐藏模式的不同排列,将文本字段的标签与文本字段一起隐藏以查看不同的行为。
// hidemode 3 == ignore in layout
// hidemode 2 == zero size and zero gaps
// hidemode 1 == zero size
// hidemode 0 == same as visible
MigLayout layout = new MigLayout("wrap 2, hidemode 3");
JComponent content = new JPanel(layout);
JPopupMenu popup = new JPopupMenu();
for (int i = 0; i < 5; i++) {
JTextField field = new JTextField("field " + i, 20);
field.setName(field.getText());
JLabel label = new JLabel("Label " + i);
label.setLabelFor(field);
content.add(label);
content.add(field);
popup.add(new JCheckBoxMenuItem(new ToggleVisibilityAction(field, true)));
}
content.setComponentPopupMenu(popup);
// action to toggle the visibility of a target component
// optionally w/out its label
public static class ToggleVisibilityAction extends AbstractAction {
private JComponent target;
private boolean hideLabel;
public ToggleVisibilityAction(JComponent comp, boolean hideLabel) {
super(comp.getName());
this.target = comp;
this.hideLabel = hideLabel;
putValue(SELECTED_KEY, target.isVisible());
}
@Override
public void actionPerformed(ActionEvent e) {
boolean visible = (boolean) getValue(SELECTED_KEY);
target.setVisible(visible);
if (hideLabel && target.getClientProperty("labeledBy") instanceof JComponent) {
((Component) target.getClientProperty("labeledBy")).setVisible(visible);
}
target.getParent().revalidate();
}
}