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

Java 如何在仅垂直滚动窗格中布局组件?,java,swing,Java,Swing,我有一个复杂的问题,到处都找不到答案 以下是一个例子: 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

我有一个复杂的问题,到处都找不到答案

以下是一个例子:

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);
}
在这里,显然文本字段被剪切了。更准确地说,大窗格被切割。但是我希望文本字段的大小可以调整,而不是剪切,这样我们仍然可以使用它们

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

我找不到解决这个问题的办法,如果你能帮忙的话,甚至连黑客都找不到

尼科

PS:看起来ViewportLayout的代码没有包含任何这方面的代码


PS2:这是上述代码结果的上限,请参见右侧。

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

或者,适当设置文本字段的最大和首选大小(
setMaximumSize
setMinimumSize

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

因为调用0构造函数,所以得到的是“自然结果是什么”实现,它占用了太长字符串的长度。只需使用非零值调用columns构造函数即可解决此问题。试试下面这些句子:

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));
以下是生成的窗格的屏幕截图:


(来源:)

我认为“正确”的方法是使用可滚动界面:

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();
}
if(JViewport的getParent()实例){
JViewport viewport=(JViewport)getParent();
返回组件.getPreferredSize().height
我认为这些解决方案都不能解决我的问题。我希望垂直部分的当前行为保持不变,因此这排除了用手触摸任何尺寸的物体。设置列号根本不会改变布局行为,它只是间接地改变了preferredSize。我不能说我理解你想要什么。问题到底是什么?你说的“切”是什么意思?框架看起来太宽了吗?不够宽?问题是什么?当调整帧的大小时,字段被剪切而不是调整大小。这是我得到的:这是我想要的:很抱歉,我仍然不知道你的意思!“剪切”字段和调整大小的字段之间有什么区别?我能看到的两张图片之间的唯一区别是文本字段的垂直大小。。。也许您是说希望整个字段更小(包括字体大小等)?如果是这样的话,你需要,嗯,改变字体大小。这不是典型的行为——如果我把浏览器变小,我就不会得到网页的缩略图!看图片的右边。也许你会看到区别。用图片向您展示行为很复杂。您所说的“我希望文本字段中的文本被剪切”是什么意思?你想限制文本的长度吗?以下是我想要的:(我通过删除滚动窗格实现了这一点)以下是我得到的和不想要的:使文本字段不可用。我不理解对这两个答案的反对票。它们都是你想要的。不是真的,因为它们是狭义的黑客,在现实生活中,我的专栏中有其他组件,我希望在某些情况下能够使用首选的大小,等等。我转换了向上投票的点数,因为在我的示例中,它们确实有效。但这几乎不是一个解决方案。“在我的例子中,它们确实有效。但这几乎不是一个解决方案”-嗯。如果你想鼓励人们提供帮助,那么否决工作解决方案不是一个好主意!我想我已经回答了。这将破坏首选大小目的,例如破坏JFrame.pack()目的。我不想更改首选大小(手动),我希望在这种情况下,在计算视图宽度时忽略首选宽度。显然,我想要的是公共布尔getScrollableTracksViewportWidth(){return true;}非常感谢。从技术上讲,我的项目中已经使用了swingx,我将使用JXPanel和调用面板。setScrollableTracksViewPortWidth(false);在上面。这将避免自定义代码的其余部分。