Java / Swing:JScrollPane 中的 JTextArea,如何防止自动滚动?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3972337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:12:48  来源:igfitidea点击:

Java / Swing : JTextArea in a JScrollPane, how to prevent auto-scroll?

javaswingjscrollpanejtextarea

提问by SyntaxT3rr0r

here's a runnable piece of code that shows what my "problem" is.

这是一段可运行的代码,显示了我的“问题”是什么。

I've got a JTextAreawrapped in a JScrollPane. When I change the text of the JTextArea, the JScrollPanescrolls automatically to the end of the text and I don't want that.

我有一个JTextArea包裹在JScrollPane. 当我更改 的文本时JTextArea,会JScrollPane自动滚动到文本的末尾,我不希望那样。

Here are my requirements:

以下是我的要求:

  • the application should notscroll vertically automatically but...
  • the user shouldbe able to scroll vertically
  • the user should notbe able to scroll horizontally
  • the application should neverscroll horizontally
  • the JTextArea must not be editable
  • 应用程序不应自动垂直滚动,但...
  • 用户应该能够垂直滚动
  • 用户应该能够水平滚动
  • 应用程序永远不应该水平滚动
  • JTextArea 不能是可编辑的

(so even if there's more text than what can fit horizontally, neither the application nor the user should be able to scroll horizontally. While vertically, only the user should be able to scroll.)

(因此,即使文本多于可以水平放置的文本,应用程序和用户都不应该能够水平滚动。而垂直时,只有用户应该能够滚动。)

I don't know how to "fix" this: should this be fixed using JTextAreaor JScrollPanemethods?

我不知道如何“解决”这个问题:应该使用JTextAreaJScrollPane方法来解决这个问题吗?

Note that AFAICT this is nota duplicate at all of: JTextPane prevents scrolling in the parent JScrollPane

请注意,AFAICT 这根本不是重复的:JTextPane 阻止在父 JScrollPane 中滚动

Here's the kinda funny example, every 200 ms it puts new text in the JTextAreaand you can see the JScrollPanealways scrolling automatically to the end of the text.

这是一个有点有趣的例子,每 200 毫秒它就会在 中放入新文本JTextArea,你可以看到它JScrollPane总是自动滚动到文本的末尾。

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public final class TextInScrollPane extends JFrame {

    private static final Random r = new Random( 42 );

    public static void main( final String[] args ) {
        final JFrame f = new JFrame();
        f.setDefaultCloseOperation( EXIT_ON_CLOSE );
        f.setLayout(new BorderLayout());
        final JTextArea jta = new JTextArea( "Some text", 30, 30 );
        jta.setEditable( false );   // This must not be editable
        final JScrollPane jsp = new JScrollPane( jta );
        jsp.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
        jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
        f.add( jsp, BorderLayout.CENTER );
        f.pack();
        f.setLocationRelativeTo( null );
        f.setVisible(true);

        final Thread t = new Thread( new Runnable() {
            public void run() {
                while ( true ) { 
                    try {Thread.sleep( 200 );} catch ( InterruptedException e ) {}
                    final StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < 50 + r.nextInt( 75 ); i++) {
                        for (int j = 0; j < r.nextInt(120); j++) {
                            sb.append( (char) 'a' + r.nextInt(26) );
                        }
                        sb.append( '\n' );
                    }
                    SwingUtilities.invokeLater( new Runnable() {
                        public void run() {
                            jta.setText( sb.toString() );
                        }
                    } );
                }
            }
        });
        t.start();
    }

}

回答by I82Much

How to set AUTO-SCROLLING of JTextArea in Java GUI?

如何在 Java GUI 中设置 JTextArea 的自动滚动?

http://download.oracle.com/javase/1.5.0/docs/api/javax/swing/text/DefaultCaret.html#NEVER_UPDATE

http://download.oracle.com/javase/1.5.0/docs/api/javax/swing/text/DefaultCaret.html#NEVER_UPDATE

Try:

尝试:

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

This should prevent the caret from automatically making the document scroll to the bottom.

这应该可以防止插入符号自动使文档滚动到底部。

回答by SyntaxT3rr0r

Answering my own question: I'm not exactly sure this is the best way to solve my issue, but setting the JTextArea'scaret using setCaretPosition(0)seems to work fine:

回答我自己的问题:我不确定这是解决我的问题的最佳方法,但JTextArea's使用设置插入符号setCaretPosition(0)似乎工作正常:

jta.setText( sb.toString() );
jta.jta.setCaretPosition( 0 );

回答by Johan M

You have run into a very strange behaviour in the implementation of the Document classes. I use a DefaultStyledDocument in a JTextPane inside a JScrollPane.

您在 Document 类的实现中遇到了一个非常奇怪的行为。我在 JScrollPane 内的 JTextPane 中使用 DefaultStyledDocument。

Now, here is the wierd thing. If I update the document on the EventQueue (like you do by scheduling a runnable to run later) the scroll pane automatically scrolls to the end.

现在,这是奇怪的事情。如果我更新 EventQueue 上的文档(就像您通过安排可运行的稍后运行一样),滚动窗格会自动滚动到末尾。

However, the document classes claim to be thread safe and actually updatable from another thread. If I make sure to update on anotherthread than the EventQueue everything works fine but the scroll pane does NOT scroll to the end.

然而,文档类声称是线程安全的并且实际上可以从另一个线程更新。如果我确保在另一个线程上更新而不是 EventQueue 一切正常,但滚动窗格不会滚动到最后。

I have no explanation as to why this is so, I haven't looked in the Swing source. I have been exploiting this "feature" since 2006 and it has been consistent so far :-)

我没有解释为什么会这样,我没有查看 Swing 源代码。自 2006 年以来,我一直在利用这个“功能”,到目前为止它一直是一致的 :-)