摆动布局:垂直流动

我应该使用什么LayoutManager来实现FlowLayout的转置版本?

基本上,我想要一个垂直列表,如果它不能适合一列中的所有组件,则它会占用多列。

+------------------------+ | item 1 | | item 2 | | item 3 | | item 4 | | item 5 | | item 6 | | item 7 | | item 8 | +------------------------+ 

要么

 +------------------------+ | item 1 item 7 | | item 2 item 8 | | item 3 | | item 4 | | item 5 | | item 6 | +------------------------+ 

这种包装逻辑需要动态发生,即在调整容器大小时。

我正在研究我自己的问题的解决方案(非常相似:我需要垂直流动但水平约束宽度),我得到了一个快速的例子工作,也许它让你开始使用自定义布局管理器:

在此处输入图像描述

在此处输入图像描述

 import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager2; import java.util.Random; import java.util.Set; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import com.google.common.collect.Sets; public class VerticalFlowLayout implements LayoutManager2 { final private Set components = Sets.newLinkedHashSet(); private int hgap = 0; private int vgap = 0; public void setHGap(int hgap) { this.hgap = hgap; } public void setVGap(int vgap) { this.vgap = vgap; } @Override public void addLayoutComponent(Component comp, Object constraints) { this.components.add(comp); } /* these 3 methods need to be overridden properly */ @Override public float getLayoutAlignmentX(Container target) { // TODO Auto-generated method stub return 0; } @Override public float getLayoutAlignmentY(Container target) { // TODO Auto-generated method stub return 0; } @Override public void invalidateLayout(Container target) { // TODO Auto-generated method stub } @Override public void addLayoutComponent(String name, Component comp) { this.components.add(comp); } @Override public void layoutContainer(Container parent) { int x = 0; int y = 0; int columnWidth = 0; for (Component c : this.components) { if (c.isVisible()) { Dimension d = c.getPreferredSize(); columnWidth = Math.max(columnWidth, d.width); if (y+d.height > parent.getHeight()) { x += columnWidth + this.hgap; y = 0; } c.setBounds(x, y, d.width, d.height); y += d.height + this.vgap; } } } /* these 3 methods need to be overridden properly */ @Override public Dimension minimumLayoutSize(Container parent) { return new Dimension(0,0); } @Override public Dimension preferredLayoutSize(Container parent) { return new Dimension(200,200); } @Override public Dimension maximumLayoutSize(Container target) { return new Dimension(600,600); } @Override public void removeLayoutComponent(Component comp) { this.components.remove(comp); } public static void main(String[] args) { JFrame frame = new JFrame("VerticalFlowLayoutTest"); VerticalFlowLayout vfl = new VerticalFlowLayout(); JPanel panel = new JPanel(vfl); vfl.setHGap(20); vfl.setVGap(2); int n = 19; Random r = new Random(12345); for (int i = 0; i < n; ++i) { JLabel label = new JLabel(labelName(i,r)); panel.add(label); } frame.setContentPane(panel); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private static String labelName(int i, Random r) { StringBuilder sb = new StringBuilder(); sb.append("label #"); sb.append(i); sb.append(" "); int n = r.nextInt(26); for (int j = 0; j < n; ++j) sb.append("_"); return sb.toString(); } } 

非常简单,你只需要这个。

 yourPanel.setLayout(new BoxLayout(yourPanel, BoxLayout.Y_AXIS)); 

在此之后,您只需将视图添加到您的面板,您将获得垂直流布局。

我将GridLayout修改为按列排列组件而不是按行排列组件:

http://forums.oracle.com/forums/thread.jspa?messageID=5716765#5716765

您需要一个自定义布局管理器,或者您可以使用GridBagLayout之类的东西来控制自己。

一个例子:

 Component parent = ...; GridBagConstraints c = ...; //set other parameters c.gridx = 0; c.gridy = 0; parent.add([component1], c); c.gridy++; parent.add([component2], c); c.gridy++; 

这篇文章很老:)

下面链接中的代码不能正常工作(计算不可见项目的高度,这是错误的!) http://www.java2s.com/Code/Java/Swing-JFC/AverticallayoutmanagersimilartojavaawtFlowLayout.htm

我换了一些零件,现在工作正常。

我也会清理插图,如果你需要,请自行添加。 谢谢

 package Common; /** * @author Pasban */ import java.awt.*; import java.util.*; public class VerticalLayout implements LayoutManager { public final static int CENTER = 0; public final static int RIGHT = 1; public final static int LEFT = 2; public final static int BOTH = 3; public final static int TOP = 1; public final static int BOTTOM = 2; private int vgap; private int alignment; private int anchor; private Hashtable comps; public VerticalLayout() { this(5, CENTER, TOP); } public VerticalLayout(int vgap) { this(vgap, CENTER, TOP); } public VerticalLayout(int vgap, int alignment) { this(vgap, alignment, TOP); } public VerticalLayout(int vgap, int alignment, int anchor) { this.vgap = vgap; this.alignment = alignment; this.anchor = anchor; } private Dimension layoutSize(Container parent, boolean minimum) { Dimension dim = new Dimension(0, 0); Dimension d; synchronized (parent.getTreeLock()) { int n = parent.getComponentCount(); for (int i = 0; i < n; i++) { Component c = parent.getComponent(i); if (c.isVisible()) { d = minimum ? c.getMinimumSize() : c.getPreferredSize(); dim.width = Math.max(dim.width, d.width); dim.height += d.height; if (i > 0) { dim.height += vgap; } } } } Insets insets = parent.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom + vgap + vgap; return dim; } public void layoutContainer(Container parent) { Insets insets = parent.getInsets(); synchronized (parent.getTreeLock()) { int n = parent.getComponentCount(); Dimension pd = parent.getSize(); int y = 0; for (int i = 0; i < n; i++) { Component c = parent.getComponent(i); Dimension d = c.getPreferredSize(); if (c.isVisible()) { y += d.height + vgap; } } y -= vgap; if (anchor == TOP) { y = insets.top; } else if (anchor == CENTER) { y = (pd.height - y) / 2; } else { y = pd.height - y - insets.bottom; } for (int i = 0; i < n; i++) { Component c = parent.getComponent(i); Dimension d = c.getPreferredSize(); if (!c.isVisible()) { continue; } int x = 1; int wid = pd.width - 3; c.setBounds(x, y, wid, d.height); y += d.height + vgap; } } } public Dimension minimumLayoutSize(Container parent) { return layoutSize(parent, false); } public Dimension preferredLayoutSize(Container parent) { return layoutSize(parent, false); } public void addLayoutComponent(String name, Component comp) { } public void removeLayoutComponent(Component comp) { } public String toString() { return getClass().getName() + "[vgap=" + vgap + " align=" + alignment + " anchor=" + anchor + "]"; } } 

Jason S的解决方案适合我。 我纠正的唯一问题是我没有com.google.common.collect.Sets或java.collections.LinkedHashSet libs(Java 7)…

所以我只是替换

 final private Set components = Sets.newLinkedHashSet(); 

通过

 final private List components = new LinkedList<>(); 

一切似乎都可以:)