使 JScrollPane 自动一直向下滚动

发布于 2024-08-26 02:58:06 字数 99 浏览 19 评论 0原文

我正在尝试使用 JTextArea 实现 JScrollPane。 JTextArea 正在被附加,我希望 JScrollPane 在添加更多文本时继续向下滚动。如何才能实现这一目标?

I am trying to implement a JScrollPane with a JTextArea. The JTextArea is being appended to, and I want the JScrollPane to keep scrolling down as more text is added. How can this be achieved?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

っ左 2024-09-02 02:58:06

对于(我认为是)更简单的答案,请查看: 文本区域滚动

在 JDK5 之前,您必须在每次追加后手动更改插入符号的位置。您现在可以将此行为设置为默认行为,如下所示:

 JTextArea textArea = new JTextArea();
 DefaultCaret 插入符号 = (DefaultCaret)textArea.getCaret();
 caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

这样做的好处是您不需要在代码中多次使用此代码段!

For (what I think is) a simpler answer check out: Text Area Scrolling.

Prior to JDK5, you would have to manually change the caret's position after each append. You can now give this behaviour as a default like this :

 JTextArea textArea = new JTextArea();
 DefaultCaret caret = (DefaultCaret)textArea.getCaret();
 caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

The advantage of this is that you don't need to use this snippet more than once in your code!

故人爱我别走 2024-09-02 02:58:06

我在这里找到了答案:
JScrollPane 和 JList 自动滚动

scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    });

I found the answer here:
JScrollPane and JList auto scroll

scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    });
吃颗糖壮壮胆 2024-09-02 02:58:06

如果您不断向其中写入数据,您可以使用:

textArea.setCaretPosition(textArea.getDocument().getLength());

添加新数据后。

这将自动在 JScorllPane 中一直向下滚动。

If you are constantly writing data to it you could use:

textArea.setCaretPosition(textArea.getDocument().getLength());

just after you add the new data.

This would automatically scroll all the way down the JScorllPane.

妳是的陽光 2024-09-02 02:58:06

这是解决方案。

JTextArea textArea = new JTextArea();
DefaultCaret caret = (DefaultCaret)textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);` 

Here is the solution.

JTextArea textArea = new JTextArea();
DefaultCaret caret = (DefaultCaret)textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);` 
反目相谮 2024-09-02 02:58:06

接受的解决方案效果很好,但仅当文本区域可编辑时,即没有 jTextArea.setEditable(false)Krigath 建议的解决方案更通用,但存在此处提出的问题JScrollPane 和 JList 自动滚动。使用该问题的答案,您可以获得通用的解决方案,例如:

        JScrollPane scrollPane = new JScrollPane(jTextArea);

    verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
    scrollPane.getVerticalScrollBar().addAdjustmentListener(
            e -> {
                if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0)
                    return;
                e.getAdjustable().setValue(e.getAdjustable().getMaximum());
                verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
            });

仅当垂直滚动条扩展时,窗格才会向下滚动,以响应附加的文本行。

我承认可以找到一种无需额外变量即可过滤事件的方法,如果有人发布它,我将不胜感激。

The accepted solution works good, but only when the text area is editable, i.e. without jTextArea.setEditable(false) . The solution suggested by Krigath is more general, but has the problem as asked here JScrollPane and JList auto scroll. Using answers from that question you can get general solution, e.g.:

        JScrollPane scrollPane = new JScrollPane(jTextArea);

    verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
    scrollPane.getVerticalScrollBar().addAdjustmentListener(
            e -> {
                if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0)
                    return;
                e.getAdjustable().setValue(e.getAdjustable().getMaximum());
                verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
            });

The Pane then is scrolled down only when vertical scroll bar is expanding, in response to appended lines of text.

I admit that that a method to filter events without extra variables could be found, and would appreciate if somebody post it.

孤檠 2024-09-02 02:58:06

解决方法是可能的:您可以将该侦听器声明为一个类,然后在需要它的事件上实例化它。之后,您可以在强制重新绘制屏幕后删除该类。就像魅力一样。

A work around is possible: you can declare that listener as a class then instantiate it on the event where it is needed. After which you can remove the class after forcing a repaint of the screen. Works like a charm.

墨落成白 2024-09-02 02:58:06

我查看了答案,发现@user9999 答案对于那些希望滚动条连续滚动的人来说是一个很好的解决方案。我编辑了代码,去掉了变量。当用户手动滚动时,它会使滚动停止。如果用户滚动到文本区域或滚动区域的末尾,自动滚动将继续。

(正如 @user9999 建议我删除该变量并添加 jScrollPane1.getHeight() 作为测量值,以便在当前滚动条值低于最大值时停止滚动)

<强>这是解决方法:

jScrollPane1.getVerticalScrollBar().addAdjustmentListener(
e -> {
    if ((e.getAdjustable().getValue() - e.getAdjustable().getMaximum()) > -jScrollPane1.getHeight() - 20){
        e.getAdjustable().setValue(e.getAdjustable().getMaximum());
    }   
});

编辑:

-20添加到-jScrollPane1.getHeight() - 20,因为有时没有它就不会滚动,我猜测 -20 可以根据 TextArea 的字体大小进行更改。

I was look at the answers and found that @user9999 answer is a good solution for those who want the scrollbar continuously scroll. I edited the code, got rid of the variable. It make the scrolling stop - when the user is scrolling manually. If the user scrolls to the end of the textarea or scrollarea, the auto scrolling continues.

(also as @user9999 suggested i removed the variable and added the jScrollPane1.getHeight() as the measure value to stop scrolling if the current scrollbar value is lower than max)

Here is the workaround:

jScrollPane1.getVerticalScrollBar().addAdjustmentListener(
e -> {
    if ((e.getAdjustable().getValue() - e.getAdjustable().getMaximum()) > -jScrollPane1.getHeight() - 20){
        e.getAdjustable().setValue(e.getAdjustable().getMaximum());
    }   
});

Edit:

Added -20 to the -jScrollPane1.getHeight() - 20 as it is sometimes doesnt scroll without it, i guess the -20 can be changed depends on the font size of the TextArea.

暗地喜欢 2024-09-02 02:58:06

如果要在多线程程序中使用自动滚动,请务必小心。
例如,如果某个地方有一个类似的方法

public void addNewLine(String s){
        textPane.setText(textPane.getText()+"\n"+s);
        if(autoscrollCheckBox.isSelected()){
            this.revalidate();
            JScrollBar vertical = scrollPane.getVerticalScrollBar();
            vertical.setValue(vertical.getMaximum());
        }
}

,如果从另一个线程调用 addNewLine (或 Vertical.setValue(...)) 方法,您将得到以下异常。 (特别是,如果您尝试调整窗口大小或在启用自动滚动的情况下尝试滚动)

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.text.BoxView.calculateMajorAxisRequirements(BoxView.java:871)
at javax.swing.text.BoxView.checkRequests(BoxView.java:930)
at javax.swing.text.BoxView.getMinimumSpan(BoxView.java:568)
...

原因是,该方法的多线程调用扰乱了 Swings 的事件处理,因此您将得到随机结果或就像上面的错误(阅读更多这里)。

正确的方法是调用 SwingUtilities.invokeLater(...):

public void addNewLine(String s){
       SwingUtilities.invokeLater( () -> {
            textPaneOutput.setText(textPaneOutput.getText()+"\n"+s);
            if(autoscrollCheckBox.isSelected()){
                this.revalidate();
                JScrollBar vertical = scrollPane.getVerticalScrollBar();
                vertical.setValue(vertical.getMaximum());
            }
        });
 }

这样您就可以线程安全地自动滚动!

Be careful if you're about to use auto scroll within a multithreaded program.
Like for example if somewhere is a method like

public void addNewLine(String s){
        textPane.setText(textPane.getText()+"\n"+s);
        if(autoscrollCheckBox.isSelected()){
            this.revalidate();
            JScrollBar vertical = scrollPane.getVerticalScrollBar();
            vertical.setValue(vertical.getMaximum());
        }
}

You will get the following exception, if the addNewLine (or the vertical.setValue(...)) method is called from another thread. (Especially, if you're try to resize the window or try to scroll while, autoscroll is enabled)

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.text.BoxView.calculateMajorAxisRequirements(BoxView.java:871)
at javax.swing.text.BoxView.checkRequests(BoxView.java:930)
at javax.swing.text.BoxView.getMinimumSpan(BoxView.java:568)
...

The reason for this is, the multithreaded call of the method is messing up with Swings' eventhandling, so you'll get random results or like above an error (read morehere).

The correct way is to call SwingUtilities.invokeLater(...):

public void addNewLine(String s){
       SwingUtilities.invokeLater( () -> {
            textPaneOutput.setText(textPaneOutput.getText()+"\n"+s);
            if(autoscrollCheckBox.isSelected()){
                this.revalidate();
                JScrollBar vertical = scrollPane.getVerticalScrollBar();
                vertical.setValue(vertical.getMaximum());
            }
        });
 }

This way you'll able to auto scroll threadsafe!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文