如何在垂直滚动窗格中布局组件?

我有一个复杂的问题,我无法在任何地方找到答案。

这是一个例子:

public static void main(final String[] args) { final JFrame frame = new JFrame("test"); final JPanel bigPane = new JPanel(new GridLayout(0, 1)); frame.setContentPane(new JScrollPane(bigPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER)); bigPane.add(new JTextField("reterterter ertertrert erterter ert")); bigPane.add(new JTextField(" ertertrert erterter ert")); bigPane.add(new JTextField("reterterter ertertrert ert")); bigPane.add(new JTextField("reterterter ertertrert erterter ")); frame.pack(); frame.setSize(frame.getSize().width/2, frame.getSize().height); frame.setVisible(true); } 

在这里,显然文本字段被切断了。 更准确地说,bigPane被削减了。 但我希望文本字段可以resize而不是剪切,所以我们仍然可以使用它们。

由于禁止出现水平滚动条,我希望布局忘记视图(bigPane)的首选宽度,并始终强制视图的宽度与视口的宽度相匹配。 就像没有水平方向的虚拟视口一样,只有垂直方向。

如果你能提供帮助的话,我找不到解决方案,甚至不是黑客。

尼科。

PS:看起来ViewportLayout的代码不包含任何代码

PS2:这里是上面代码的结果上限http://sofzh.miximages.com/java/testLayout.png见右侧。

我认为“正确”的方法是使用Scrollable接口:

 public class ScrollPaneWidthTrackingPanel extends JPanel implements Scrollable { private static final long serialVersionUID = 1L; public ScrollPaneWidthTrackingPanel(LayoutManager layoutManager) { super(layoutManager); } public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { return Math.max(visibleRect.height * 9 / 10, 1); } public boolean getScrollableTracksViewportHeight() { return false; } public boolean getScrollableTracksViewportWidth() { return true; } public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { return Math.max(visibleRect.height / 10, 1); } } 

然后,您的代码的两行必须更改为:

 final ScrollPaneWidthTrackingPanel bigPane = new ScrollPaneWidthTrackingPanel(new GridLayout(0, 1)); frame.setContentPane(new JScrollPane(bigPane)); 

并且组件应始终填充JScrollPane的整个宽度,无论框架的大小如何。 此更改具有副作用,即组件现在不会填充JScrollPane的高度。 要解决此问题,请将以下代码添加到getScrollableTracksViewportHeight方法的顶部:

 if (getParent() instanceof JViewport) { JViewport viewport = (JViewport) getParent(); return component.getPreferredSize().height < viewport.getHeight(); } 

使用JTextField构造函数,该构造函数将int作为参数。 这是文本字段中可见字符的数量。 然后,您可以使用setText初始化字段的内容(如果需要)。

或者,适当地设置文本字段的最大和首选大小setMaximumSizesetMinimumSize )。

来自JavaDoc:

参数:
text – 要显示的文本,或null
columns – 用于计算首选宽度的列数; 如果列设置为零,则首选宽度将是组件实现自然产生的任何宽度

因为你正在调用0构造函数,所以你得到了“无论结果如何”的实现,它实现了你的太长字符串的长度。 简单地调用列构造函数,使用非零将为您解决此问题。 试试这些:

 bigPane.add(new JTextField("reterterter ertertrert erterter ert",3)); bigPane.add(new JTextField(" ertertrert erterter ert",3)); bigPane.add(new JTextField("reterterter ertertrert ert",3)); bigPane.add(new JTextField("reterterter ertertrert erterter ",3)); 

以下是生成的窗格的屏幕截图:

alt text http://mcglashan.net/stackoverflow1.png