简体   繁体   English

将文本追加到JTextPane时,JTextPane的滚动条不可见

[英]Scrollbars not visible for JTextPane when appending text into JTextPane

I have a JTextPane inside JScrollPane (with horizontal policy NEVER and vertical policy ALWAYS). 我在JScrollPane中有一个JTextPane(始终使用水平策略,而始终使用垂直策略)。 I have written a method to append text in this JTextPane. 我已经编写了一种在此JTextPane中附加文本的方法。 Now there is a button and on click of the button, action listener is running doing some data manipulation and updating the data on JTextPane. 现在有一个按钮,单击该按钮,动作侦听器正在运行以进行一些数据操作并更新JTextPane上的数据。 I am using JScrollPane.update() method to refresh the appended text. 我正在使用JScrollPane.update()方法刷新附加的文本。 Text is updating correctly until the height of the JTextPane is reached. 文本正确更新,直到达到JTextPane的高度。 As more text is added, it should show vertical scrollbar and update the text. 添加更多文本时,它应显示垂直滚动条并更新文本。 But this is not happening. 但是,这没有发生。 Instead, the whole text appears as the flow is out from action listener method. 相反,当流程从动作侦听器方法中流出时,整个文本将显示。

I have tried with updating both the JTextPane and JScrollPane. 我尝试过同时更新JTextPane和JScrollPane。 But it doesn't seem to be working. 但这似乎不起作用。

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


As the loop is running, it should update the text in JTextPane as 在循环运行时,应将JTextPane中的文本更新为
dummy text 1 虚拟文字1
dummy text 2 虚拟文字2
dummy text 3 虚拟文字3
. . .

Let's suppose after dummy text 10, it reached to the JScrollPane height. 假设在伪文本10之后,它达到了JScrollPane的高度。
Now expected behaviour is -- 现在预期的行为是-
it should keep on updating new text like 它应该继续更新新文本,例如
dummy text 11 虚拟文字11
dummy text 12 虚拟文字12
.. and vertical scrollbar should appear. ..和垂直滚动条应出现。

But actual behaviour is -- 但是实际行为是-
it works fine until dummy text 10 (assuming the height of JScrollPane could hold 10 lines). 它可以正常工作,直到伪文本10(假设JScrollPane的高度可以容纳10行)。 After that the JTextPane flickers but nothing happens and as the loop completes, it shows the remaining 90 line at once with vertical scrollbar. 之后,JTextPane闪烁但没有任何反应,并且在循环完成时,它使用垂直滚动条一次显示了剩余的90行。

dummy text 11 虚拟文字11
dummy text 12 虚拟文字12
.
.
.

I guess the problem is somewhere in visibility of JScrollBar when I am appending more and more lines. 我猜这个问题是在我添加越来越多的行时JScrollBar可见性的某个地方。

Any help would be appreciated. 任何帮助,将不胜感激。

Instead, the whole text appears as the flow is out from action listener method. 相反,当流程从动作侦听器方法中流出时,整个文本将显示。

Code invoked from a listener executes on the Event Dispatch Thread (EDT) . 从侦听器调用的代码在Event Dispatch Thread (EDT)

Therefore, as has already been mentioned, your looping code is executing on the EDT . 因此,如前所述,您的循环代码正在EDT上执行。 The EDT is responsible for repainting the GUI but it can't do so until the main loop has finished executing. EDT负责重新绘制GUI,但是直到主循环执行完成后才能这样做。

it works fine until dummy text 10 (assuming the height of JScrollPane could hold 10 lines). 它可以正常工作,直到伪文本10(假设JScrollPane的高度可以容纳10行)。 After that the JTextPane flickers but nothing happens 之后,JTextPane闪烁但没有任何反应

It only appear to work because you are using Swing incorrectly: 它似乎仅能正​​常工作,因为您未正确使用Swing:

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

You should NOT be invoking the update(...) method directly. 您不应该直接调用update(...)方法。 Swing will invoke this method internally when a component needs to be repainted. 需要重绘组件时,Swing将在内部调用此方法。 Forcing the update causes the flickering. 强制更新会导致闪烁。 Don't do this! 不要这样!

Instead to update the text area you need to execute your code on a separate Thread so you don't block the EDT . 代替更新文本区域,您需要在单独的Thread上执行代码,以免阻塞EDT

One way to do this is to use a SwingWorker . 一种方法是使用SwingWorker It created the Thread for you and allows you to publish() results to your text pane as required so that the text pane is then updated correctly on the EDT. 它为您创建了线程,并允许您根据需要publish()结果publish()到文本窗格,以便随后在EDT上正确更新文本窗格。

The Concurrency link you have been given in the comments section has a section on How to Use a SwingWorker with working examples to get you started. 在注释部分获得的Concurrency链接包含有关How to Use a SwingWorker以及相关工作示例的部分,以帮助您入门。 The tutorial also explains how the EDT works. 本教程还介绍了EDT工作原理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM