Java / Swing: JTextArea в JScrollPane, как предотвратить автоматическую прокрутку? - PullRequest
8 голосов
/ 20 октября 2010

вот исполняемый фрагмент кода, который показывает мою «проблему».

У меня есть JTextArea, завернутый в JScrollPane.Когда я изменяю текст JTextArea, JScrollPane автоматически прокручивается до конца текста, и я этого не хочу.

Вот мои требования:

  • приложение не должно автоматически прокручивать по вертикали, но ...
  • пользователь должен иметь возможность прокрутки по вертикали
  • пользователь долженне иметь возможность прокрутки по горизонтали
  • приложение никогда не должно прокручивать горизонтально
  • JTextArea не должно быть редактируемым

(поэтомудаже если текста больше, чем может поместиться по горизонтали, ни приложение, ни пользователь не должны иметь возможность прокручивать по горизонтали. Хотя по вертикали, прокручивать может только пользователь.)

Я не знаю, как«исправить» это: должно ли это быть исправлено с помощью методов JTextArea или JScrollPane?

Обратите внимание, что 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();
    }

}

Ответы [ 3 ]

23 голосов
/ 20 октября 2010

Как установить автоматическую прокрутку JTextArea в графическом интерфейсе Java?

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

Это должно предотвратитькаретка от автоматического перемещения документа вниз.

1 голос
/ 08 марта 2011

Вы столкнулись с очень странным поведением при реализации классов Document. Я использую DefaultStyledDocument в JTextPane внутри JScrollPane.

Теперь вот странная вещь. Если я обновлю документ в EventQueue (как вы делаете это путем планирования запуска для запуска позже), панель прокрутки автоматически прокручивается до конца.

Однако классы документов утверждают, что они потокобезопасны и фактически могут быть обновлены из другого потока. Если я обязательно обновлю другой поток , чем EventQueue, все работает нормально, но панель прокрутки НЕ прокручивается до конца.

У меня нет объяснения, почему это так, я не заглядывал в источник Swing. Я использую эту «функцию» с 2006 года, и до сих пор она была последовательной: -)

1 голос
/ 20 октября 2010

Отвечая на мой вопрос: я не совсем уверен, что это лучший способ решить мою проблему, но установка каретки JTextArea's с помощью setCaretPosition(0), кажется, работает нормально:

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