Полосы прокрутки не видны для JTextPane при добавлении текста в JTextPane - PullRequest
0 голосов
/ 11 июня 2019

У меня есть JTextPane внутри JScrollPane (с горизонтальной политикой НИКОГДА и вертикальной политикой ВСЕГДА). Я написал метод для добавления текста в этом JTextPane. Теперь есть кнопка, и при нажатии кнопки прослушиватель действий выполняется, обрабатывая некоторые данные и обновляя данные в JTextPane. Я использую метод JScrollPane.update (), чтобы обновить добавленный текст. Текст корректно обновляется, пока не будет достигнута высота JTextPane. По мере добавления текста должна отображаться вертикальная полоса прокрутки и обновляться текст. Но этого не происходит. Вместо этого весь текст отображается как поток вне метода прослушивателя действий.

Я пытался обновить как JTextPane, так и JScrollPane. Но, похоже, это не работает.

JTextPane txt_message = new JTextPane();
txt_message.setPreferredSize(new Dimension(300,300));
JScrollPane sPane = new JScrollPane(txt_message);
sPane.setHorizontalScrollBarPolicy
           (JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
sPane.setVerticalScrollBarPolicy
           (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
sPane.setPreferredSize(new Dimension(320,320));
pnl_messagePane.add(sPane);
txt_message.setEditable(false);
DefaultCaret caret = (DefaultCaret) txt_message.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

//some other GUI elements
..... 

btn_Run.addActionListener(e->{
  for(int i=1; i<100; i++){
       appendToPanel(this.txt_message, "dummy text "+i, TextType.SUCCESS);
  }

//TextType is an enum defined in code whose value can be SUCCESS, ERROR

});



// Method for appending JTextPanel Text
private void appendToPane(JTextPane tp, String msg, TextType type)
   {
       Color c = null;
       switch(type) {
       case ERROR:
           c = Color.RED;
           break;

       case SUCCESS:
           c=Color.GREEN;
           break;
       default:
           c = Color.BLACK;
       }


       StyledDocument doc = tp.getStyledDocument();

       SimpleAttributeSet keyWord = new SimpleAttributeSet();
       StyleConstants.setForeground(keyWord, c);
       StyleConstants.setBold(keyWord, true);

       try
       {
           doc.insertString(doc.getLength(), "\n"+msg, keyWord );
       }

       catch(Exception e) { 
           System.out.println(e); 
       }

       tp.update(tp.getGraphics());

       this.sPane.update(this.sPane.getGraphics());
   }


Поскольку цикл работает, он должен обновить текст в JTextPane как
фиктивный текст 1
фиктивный текст 2
фиктивный текст 3
, , .

Давайте предположим, что после фиктивного текста 10 он достиг высоты JScrollPane.
Теперь ожидаемое поведение -
оно должно продолжать обновлять новый текст, как
фиктивный текст 11
фиктивный текст 12
.. и вертикальная полоса прокрутки должны появиться.

Но в действительности поведение -
работает нормально, пока фиктивный текст 10 (при условии, что высота JScrollPane может содержать 10 строк). После этого JTextPane мерцает, но ничего не происходит, и когда цикл завершается, он показывает оставшиеся 90 строк одновременно с вертикальной полосой прокрутки.

фиктивный текст 11
фиктивный текст 12
,
,
.

Полагаю, проблема в видимости JScrollBar, когда я добавляю все больше и больше строк.

Любая помощь будет оценена.

1 Ответ

1 голос
/ 11 июня 2019

Вместо этого весь текст появляется, когда поток выходит из метода прослушивателя действий.

Код, вызванный из прослушивателя, выполняется на Event Dispatch Thread (EDT).

ПоэтомуКак уже упоминалось, ваш код цикла выполняется на EDT.EDT отвечает за перерисовку графического интерфейса, но он не может сделать это, пока не завершится выполнение основного цикла.

он работает нормально, пока не будет фиктивного текста 10 (при условии, что высота JScrollPane может содержать 10линии).После этого JTextPane мерцает, но ничего не происходит

Кажется, что он работает только потому, что вы неправильно используете Swing:

tp.update(tp.getGraphics());
this.sPane.update(this.sPane.getGraphics());

Вы НЕ должны вызывать обновление (...)метод напрямую.Swing вызовет этот метод внутри, когда компонент должен быть перекрашен.Принудительное обновление вызывает мерцание.Не делайте этого!

Вместо того, чтобы обновлять текстовую область, вам нужно выполнить код на отдельной Thread, чтобы не блокировать EDT.

Один способсделать это, чтобы использовать SwingWorker.Он создал поток для вас и позволяет вам publish() результатов на вашей текстовой панели по мере необходимости, так что текстовая панель затем корректно обновляется в EDT.

Ссылка Concurrency, указанная вами в разделе комментариев, содержит раздел How to Use a SwingWorker с рабочими примерами, с которых можно начать.В руководстве также объясняется, как работает EDT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...