JScrollPane 中的动态 JTextArea 最终位于滚动条下方

Dynamic JTextArea in JScrollPane ends up under scroll bar

我有一个 JFrame 和一个包含 JTextArea 的 JScrollPane。滚动窗格配置为从不显示水平滚动条,并根据需要显示垂直滚动条。 随着文本区域中文本的增长,垂直滚动条最终出现,隐藏了文本区域的一部分。我希望滚动条在出现时根据需要调整其内容的大小。

我发现的一种解决方法是始终显示垂直滚动条,但这看起来不太好,因为很少需要它。

在我的系统中输入足够的文本后,下面的代码片段重现了该问题 (Windows 10)

import javax.swing.*;
import java.awt.*;
import static javax.swing.ScrollPaneConstants.*;

public class Test {
    public static void main(String[] args) {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.add(new JLabel("text"));
        panel.add(new JLabel("text"));
        panel.add(new JLabel("text"));

        JTextArea textArea = new JTextArea();
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setText("This text fits");
        panel.add(textArea);

        JScrollPane scrollPane =
                new JScrollPane(panel, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_NEVER);

        JFrame frame = new JFrame("Title");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().add(scrollPane);

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

要解决此问题,请更改:

JTextArea textArea = new JTextArea();

收件人:

JTextArea textArea = new JTextArea(1,20);

通过为文本区域提供大小提示,滚动窗格能够在添加更多文本时更好地处理它。

只是组件放置的问题。参考以下代码:

public TestFrame() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    setContentPane(contentPane);
    contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));

    JScrollPane scrollPane = new JScrollPane();
    contentPane.add(scrollPane);

    JPanel panel = new JPanel();
    scrollPane.setColumnHeaderView(panel);
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

    JLabel lblNewLabel = new JLabel("text");
    panel.add(lblNewLabel);

    JLabel lblNewLabel_2 = new JLabel("text");
    panel.add(lblNewLabel_2);

    JLabel lblNewLabel_1 = new JLabel("text");
    panel.add(lblNewLabel_1);

    JTextArea textArea = new JTextArea();
    textArea.setLineWrap(true);
    textArea.setText("This text fits");
    scrollPane.setViewportView(textArea);
}

希望这会有所帮助。 :-)

覆盖 doLayout() 并做任何你想做的事情,在 doLayout() 中,你对如何处理你的子组件有最终决定权(在布局管理器的工作完成后)。

但是你需要先把textArea和scrollPane变成属性,因为后面需要引用它们:

private static JTextArea textArea;
private static JScrollPane scrollPane;

public static void main(String[] args) {
    JPanel panel = new JPanel() {
        @Override
        public void doLayout() {
            super.doLayout();

            if (scrollPane.getVerticalScrollBar().isVisible()) {
                textArea.setSize(textArea.getWidth() - 3, textArea.getHeight());
            }
        }
    };

尝试不显示水平滚动条并没有多大帮助。

相反,您需要实现 Scrollable 接口来告诉滚动窗格面板应始终适合滚动窗格的宽度。这将导致文本区域中的文本在添加文本时被正确换行。

您可以使用 Scrollable Panel 而不是实现 Scrollable 接口,它允许您使用 class.

的方法更改可滚动属性

您只需更改您的代码如下:

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