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

发布于 2024-09-28 01:27:50 字数 2440 浏览 7 评论 0原文

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

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

以下是我的要求:

  • 应用程序不应该自动垂直滚动,但是...
  • 用户应该能够垂直滚动
  • 用户不应该能够水平滚动
  • 应用程序不应该水平滚动
  • JTextArea 不得可编辑

(因此,即使文本多于水平方向所能容纳的内容,应用程序和用户都不应该能够水平滚动。垂直,只有用户应该能够滚动。)

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

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

这是有点有趣的例子,每 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();
    }

}

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

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

Here are my requirements:

  • the application should not scroll vertically automatically but...
  • the user should be able to scroll vertically
  • the user should not be able to scroll horizontally
  • the application should never scroll horizontally
  • the JTextArea must not be editable

(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 JTextArea or JScrollPane methods?

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

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

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();
    }

}

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

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

发布评论

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

评论(3

太阳公公是暖光 2024-10-05 01:27:50

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

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

尝试:

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

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

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

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.

箹锭⒈辈孓 2024-10-05 01:27:50

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

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

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

jta.setText( sb.toString() );
jta.jta.setCaretPosition( 0 );
梓梦 2024-10-05 01:27:50

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

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

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

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

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.

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.

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

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 :-)

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