Java ScrollPane(里面有一个 TextArea)无法以编程方式滚动到顶部

Java ScrollPane (with a TextArea inside) can not scroll to top programmatically

为了抽象这个问题,我放了 2 个按钮。一个叫做"Add & toTop",另一个叫做"toTop"

而且最开始的textArea里面没有文字

然后我为 "Add & toTop" 按钮添加 actionListener,如下所示:

btn1.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                textArea1.setText("jhggjhg\nhugffsrdtfg\ngfdrtdf\nhgftrsdf\nytfresrdcfvg\nuytyrdtesrdfgg\ntdrfygvhct\njh"
                        + "gfda\njftyuyiugcf\nhfuygihvftyughbuy\nhgyuftydfhgfyc\ndstryrfdts");
                //A long enough String
                JScrollBar jb = scrollPane1.getVerticalScrollBar();
                jb.setValue(jb.getMinimum());
                scrollPane1.repaint();
            }
        });

所以第一个按钮的功能是:"Add some text and Scroll to Top"

但是只会添加文字不会滚动到顶部

但是对于第二个按钮,我添加了一个像这样的 actionListener:

btn2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JScrollBar VerticalScrollBar =  scrollPane1.getVerticalScrollBar();
                VerticalScrollBar.setValue(VerticalScrollBar.getMinimum());

                scrollPane1.repaint();
            }
        });

所以,我在按下第一个按钮后按下第二个按钮,第二个按钮会表现良好。 我真的很困惑为什么第一个按钮不会滚动到顶部:<

一个简单的解决方案可能是使用 JTextArea#setCaretPosition,例如

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextArea ta;

        public TestPane() {
            setLayout(new BorderLayout());
            ta = new JTextArea(5, 20);
            add(new JScrollPane(ta));

            JButton btn = new JButton("Add and to top");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    ta.setText("jhggjhg\nhugffsrdtfg\ngfdrtdf\nhgftrsdf\nytfresrdcfvg\nuytyrdtesrdfgg\ntdrfygvhct\njh"
                            + "gfda\njftyuyiugcf\nhfuygihvftyughbuy\nhgyuftydfhgfyc\ndstryrfdts");
                    ta.setCaretPosition(0);
                }
            });

            add(btn, BorderLayout.SOUTH);
        }


    }

}

我玩过 scrollRectToVisible,但最终不得不使用 SwingUtilites.invokeLater 来让它工作,例如...

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        ta.scrollRectToVisible(new Rectangle(0, 0, 10, 10));
    }
});

所以我会说 setCaretPosition 在这种情况下是更简单的解决方案