Вопрос

У меня где-то есть пара тысяч строк кода, и я заметил, что мой JTextPane мерцает, когда я слишком часто его обновляю..Я написал здесь упрощенную версию:

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

public class Test
{
    static JFrame f;
    static JTextPane a;
    static final String NL = "\n";

    public static void main(String... args)
    {
        EventQueue.invokeLater(new Runnable(){
        public void run()
        {
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.setSize(400, 300);
        f.setLocationRelativeTo(null);

        a = new JTextPane();
        f.add(new JScrollPane(a));

        new Thread(new Runnable(){
            public void run()
            {
                int i = 0;
                StringBuffer b = new StringBuffer();
                while(true)
                {
                    b.append(++i+NL);
                    a.setText(b.toString());
                    a.setCaretPosition(b.length());
                    try{Thread.sleep(10);}catch(Exception e){}
                }
            }
        }).start();
        }
        });

    }
}

Это для компонента GUI в стиле терминала (cmd)--

Я думаю, что я сделал здесь всю возможную оптимизацию, включая наличие \n в качестве конечной переменной, чтобы она не создавалась сотни раз.Тем не менее, мерцание заметно и неприемлемо.Через несколько минут компонент полностью застывает.Я должен обновить компонент очень быстро, и при обновлении панель должна быть прокручена до самого низа.

Я подумывал о создании своей собственной версии JTextPane с нуля, но я хотел бы посмотреть, есть ли у вас, ребята, более простое решение.

Это было полезно?

Решение

Часть вашей ошибки заключается в том, что вы обращаетесь к компоненту Swing извне потока событий!ДА, setText() является потокобезопасным, но методы Swing не являются потокобезопасными, если они явно не объявлены как таковые.Таким образом, setCaretPosition() не является потокобезопасным и должен быть доступен из потока событий.Почти наверняка именно поэтому ваше приложение в конечном итоге зависает.

ПРИМЕЧАНИЕ: JTextPane наследует свой setText() способ из JEditorPane и его setCaretPosition способ из JTextComponent, что объясняет ссылки в предыдущем абзаце , не ведущие на JTextPane Страница JavaDoc.

Чтобы быть потокобезопасным, вам действительно нужно, по крайней мере, вызвать setCaretPosition() из потока событий, что вы можете сделать с помощью такого кода, как этот:

SwingUtilities.invokeAndWait(new Runnable() {
  public void run() {
    a.setText(b.toString());
    a.setCaretPosition(b.length());
  }
}

И поскольку ты должен позвонить setCaretPosition() из потока событий вы также можете вызвать setText() из того же самого места.

Вполне возможно, что вам не понадобится вручную устанавливать положение курсора.Ознакомьтесь с разделом "Изменения курсора" в JavaDoc для JTextКомпонент.

Наконец, возможно, вы захотите ознакомиться с серией из двух статей:

Другие советы

Не уверен, сработает ли это, но вы могли бы попробовать использовать insertString() метод отображения текстовой панели Document пример.Я бы попробовал поставить один пробел в конце документа и сохранить курсор расположенным после этого пробела;но когда вы вставляете строку, вставляйте ее перед пробелом.Таким образом, положение курсора автоматически сохранится в конце документа.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top