【发布时间】:2020-01-26 14:00:51
【问题描述】:
我正在尝试构建一个面板,其组件水平布局,如果位置不足则自动换行和垂直滚动条。
类似这样的:
+-----------------+
|[1][2][3][4][5] |
| |
+-----------------+
缩小宽度:
+-----------+
|[1][2][3] |
|[4][5] |
+-----------+
再次缩小宽度,出现滚动条:
+---------+
|[1][2] ^|
|[3][4] v|
+---------+
我离解决方案不远了:
public class TestFlow extends JFrame {
public TestFlow() {
getContentPane().setLayout(new BorderLayout());
JPanel panel = new JPanel(new FlowLayout());
JScrollPane scroll = new JScrollPane(panel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(scroll, BorderLayout.CENTER);
panel.add(new MyComponent("A"));
panel.add(new MyComponent("B"));
panel.add(new MyComponent("C"));
panel.add(new MyComponent("D"));
panel.add(new MyComponent("E"));
panel.add(new MyComponent("F"));
panel.add(new MyComponent("G"));
panel.add(new MyComponent("H"));
panel.add(new MyComponent("I"));
panel.add(new MyComponent("J"));
panel.add(new MyComponent("K"));
panel.add(new MyComponent("L"));
panel.add(new MyComponent("M"));
panel.add(new MyComponent("N"));
panel.add(new MyComponent("O"));
scroll.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
Dimension max=((JScrollPane)e.getComponent()).getViewport().getExtentSize();
// panel.setMaximumSize(new Dimension(max.width,Integer.MAX_VALUE));
panel.setPreferredSize(new Dimension(max.width,Integer.MAX_VALUE));
// panel.setPreferredSize(max);
panel.revalidate();
// panel.repaint();
// System.out.println(panel.getSize().width+"--"+max.width);
}
});
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500, 200);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new TestFlow().setVisible(true));
}
private static class MyComponent extends JLabel {
public MyComponent(String text) {
super(String.join("", Collections.nCopies((int)(Math.round(Math.random()*4)+4), text)));
setOpaque(true);
setBackground(Color.YELLOW);
}
}
}
,但仍有奇怪的行为:
用解决方案panel.setPreferredSize(new Dimension(max.width,Integer.MAX_VALUE));
- 调整窗口大小后,面板变空。我必须手动移动滚动条才能显示内容
- 滚动条始终可见,但不应该
用解决方案panel.setPreferredSize(max);
- 调整窗口大小后,面板不会重新布局。我必须再次手动移动窗口才能重新布置内容。
- 滚动条永远不可见,但它应该可见。
该代码中有什么建议吗?
[编辑] 我将原始代码复杂化,并应用了迄今为止提供的建议。
出于设计目的,我想在面板顶部使用 MigLayout。一开始,一切都布置得很好。放大窗口时,它也可以工作。但不是减少窗口。 addComponentListener不会带来任何附加值。
public class TestMigFlow extends JFrame {
public TestMigFlow() {
getContentPane().setLayout(new BorderLayout());
JPanel panel = new JPanel(new MigLayout("debug, fill, flowy", "[fill]"));
JScrollPane scroll = new JScrollPane(panel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(scroll, BorderLayout.CENTER);
panel.add(new JLabel("A title as spearator "), "growy 0");
JPanel sub = new JPanel(new WrapLayout());
// panel.add(sub, "growx 0"); // Works well on shrink but not on grow
panel.add(sub); // Works well on grow but not on shrink
sub.add(new MyComponent("A"));
sub.add(new MyComponent("B"));
sub.add(new MyComponent("C"));
sub.add(new MyComponent("D"));
sub.add(new MyComponent("E"));
sub.add(new MyComponent("F"));
sub.add(new MyComponent("G"));
sub.add(new MyComponent("H"));
sub.add(new MyComponent("I"));
sub.add(new MyComponent("J"));
sub.add(new MyComponent("K"));
sub.add(new MyComponent("L"));
sub.add(new MyComponent("M"));
sub.add(new MyComponent("N"));
sub.add(new MyComponent("O"));
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
Dimension max = new Dimension(scroll.getWidth(), Short.MAX_VALUE);
panel.setMaximumSize(max);
panel.repaint();
}
});
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 500);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new TestMigFlow().setVisible(true));
}
private static class MyComponent extends JLabel {
public MyComponent(String text) {
super(String.join("", Collections.nCopies((int) (Math.round(Math.random() * 4) + 4), text)));
setOpaque(true);
setBackground(Color.YELLOW);
}
}
【问题讨论】:
-
链接问题中的
WrapLayout真的可以做到。但附带说明:在 any 大小的计算中使用Integer.MAX_VALUE会严重、严重地搞砸事情。任何像MAX_VALUE + 1这样的计算都会导致结果为 negative 值。最接近您应该使用的“无限大”组件的是Short.MAX_VALUE(但在 > 20 年的 Swing 编程中,我只在非常特定的上下文中使用过这个一次 - 通常,更精确地知道组件的大小...) -
谢谢。 WrapLayout 是该示例的解决方案。集成为由 MigLayout 布局的 Panel 中的组件,它的行为不太好。我将更新示例。
-
我已将示例更新为更复杂的示例。
标签: java swing jscrollpane miglayout flowlayout