设置 JTextArea 的高度而不是宽度

Set height but not width of JTextArea

我在 JPanel 中有多个 JTextArea。我正在使用 BoxLayout 使它们垂直对齐并填充容器的宽度。

它有效,但它们似乎也会扩展以填满整个高度。

我真正想要的很简单 - 一个包含文本的文本区域,我可以在其中控制宽度但允许高度随着添加更多行而动态缩放。上面的方法只是我最好的尝试。如果有使用不同的布局管理器、不同的文本组件等的解决方案,那是可行的。

下面的最小可验证示例:

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setPreferredSize(new Dimension(300, 300));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel textAreas = new JPanel();
    textAreas.setLayout(new BoxLayout(textAreas, BoxLayout.Y_AXIS));

    JTextArea area1 = new JTextArea();
    area1.append("this is a string");
    area1.setLineWrap(true);
    area1.setWrapStyleWord(true);
    textAreas.add(area1);

    JTextArea area2 = new JTextArea("and another that is much longer, so that it wraps to the next line");
    area2.setLineWrap(true);
    area2.setWrapStyleWord(true);
    textAreas.add(area2);

    JScrollPane scrollPane = new JScrollPane();
    scrollPane.setViewportView(textAreas);

    frame.add(scrollPane);
    frame.pack();
    frame.setVisible(true);
}

我自己研究过这个主题,包括查看不同的布局管理器 (http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html),并检查网站上的其他问题,但我没有太多运气。

TLDR:我能否做到让布局的每个元素都具有与其内容成比例但宽度固定的高度?如果有怎么办?

What I really want is simple - a text area that wraps text where I can control the width but allow the height to scale dynamically as more lines are added.

BoxLayout 遵循最大尺寸,因此文本区域会增长以填满面板中所有可用的 space。您可以使用类似以下的方法将 getMaximumSize() 方法覆盖为 return 首选高度:

JTextArea area1 = new JTextArea()
{
    public Dimension getMaximumSize()
    {
        Dimension d = super.getMaximumSize();
        d.height = getPreferredSize().height;

        return d;
    }
};

It works...

不是真的。使框架更宽,文本将展开。然后缩小边框,就会出现滚动条。即文字不会再换行

您需要做的是强制添加到滚动窗格的面板与视口宽度相同。这将使包装正常工作。

您可以通过在面板上实现 Scrollable 界面来完成此操作。具体来说,您需要将 getScrollableTracksViewportWidth() 方法重写为 return true.

或者更简单的解决方案是使用 Scrollable Panel class,它允许您设置面板的属性来控制此行为。

您可以将 JPanel 替换为 ScrollablePanel:

//JPanel textAreas = new JPanel();
ScrollablePanel textAreas = new ScrollablePanel();
textAreas.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );

编辑:

If there is a solution that uses a different layout manager

在不覆盖文本区域的 getMaximumSize() 方法的情况下,当使用 Scrollable Panel 时,您应该能够使用以下布局管理器。

GridBagLayout 允许您指定 "weightx" 约束。这将允许组件填充面板中所有可用的 space。

或者,如果您不喜欢指定 GridBagLayout 的所有约束,您可以使用 Relative Layout,它支持 vertical/horizontal 组件以其首选大小布局。

您只需要使用以下命令强制组件填充水平 space:

//textAreas.setLayout(new BoxLayout(textAreas, BoxLayout.Y_AXIS));
RelativeLayout rl = new RelativeLayout(RelativeLayout.Y_AXIS);
rl.setFill( true );
textAreas.setLayout(rl);