2013-05-14 74 views
1

在下面的代码中,我想写入JEditorPane的数字0到10000.但是,JEditorPane不会显示任何东西,除非它完全完成(一次打印0到10000)或者os给它时间来刷新和显示内容。无论是哪种情况,应用程序在一段时间内都没有响应,而用户认为应用程序崩溃了。无论如何,我们可以强制jEditorPane显示更新的内容,即使它仍然很忙?我尝试了invokeAndWait,但在这里没有帮助,因为我们不能从事件分派器线程调用invokeAndWait。快速写入JEditorPane

换句话说,如果我将Thread.sleep(0)替换为Thread.sleep(50),它可以正常工作,并在结果发生时显示结果打印,但添加50毫秒的延迟会使其非常缓慢。我所需要的就是不时更新JEditorPane,以便用户不会认为应用程序崩溃。 我更喜欢只修改updateMessages()。 这里是我的代码:

import javax.swing.JEditorPane; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.SwingUtilities; 
import javax.swing.text.Document; 
import javax.swing.text.html.HTMLEditorKit; 
import javax.swing.text.html.StyleSheet; 

public class CMessageWindowStack { 

    private static final String MESSAGE = "msg"; 
    private JScrollPane scrollPane; 
    public JEditorPane editorPane; 
    private HTMLEditorKit kit; 
    private String msgBuffer=new String(""); 
    private static CMessageWindowStack window=null; 
    private static JFrame frameContainer=null; 

    private CMessageWindowStack() 
    { 
     editorPane = new JEditorPane(); 
     editorPane.setEditable(false); 
     editorPane.setContentType("text/html"); 
     kit = new HTMLEditorKit(); 
     editorPane.setEditorKit(kit); 

     StyleSheet styleSheet = kit.getStyleSheet(); 
     styleSheet.addRule("."+MESSAGE+" {font: 10px monaco; color: black; }"); 

     Document doc = kit.createDefaultDocument(); 
     editorPane.setDocument(doc); 
     scrollPane = new JScrollPane(editorPane); 
    } 
    public static CMessageWindowStack getInstance(){ 
     if (null==window) 
     {window=new CMessageWindowStack();} 
     return window; 
    } 
/** 
* The core 
* @param sMessage 
* @param sType 
*/ 
    private void updateMessages(final String sMessage, final String sType) 

    { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 

     String sMessageHTML=""; 
     String sTypeText=""; 
     if (!sMessage.equals("\r\n")){ 
      sTypeText = sType+": "; 
     } 

     sMessageHTML = sMessage.replaceAll("(\r\n|\n)", "<br/>"); 
     if (!sMessageHTML.equals("<br/>")) 
     { 
      sMessageHTML = "<SPAN CLASS="+sType+">"+ sTypeText+sMessageHTML + "</SPAN>"; 
     } 

     msgBuffer=msgBuffer.concat(sMessageHTML); 
     editorPane.setText(msgBuffer); 
     if ((editorPane.getDocument()).getLength()>1){ 
      editorPane.setCaretPosition((editorPane.getDocument()).getLength()-1); 
     } 
      } 
      }); 
    } 

    public void setContainerFrame(JFrame jFrame){ 
     frameContainer = jFrame; 
     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(frameContainer.getContentPane()); 
     frameContainer.getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
       layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
       .addComponent(scrollPane) 
       ); 
     layout.setVerticalGroup(
       layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
       .addGroup(layout.createSequentialGroup() 
         .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 217, Short.MAX_VALUE)) 
       ); 
    } 

    public void setVisible(boolean bVisible){ 
     editorPane.setVisible(bVisible); 
     scrollPane.setVisible(bVisible); 
    } 

    public void printMsg(String sMessage){ 
     String sType = MESSAGE; 
     updateMessages(sMessage,sType); 
    } 

    public void printlnMsg(String sMessage){ 
     sMessage=sMessage.concat("\r\n"); 
     printMsg(sMessage); 
    } 


    public static void main(String args[]){ 
     CMessageWindowStack m_LogMgr; 
     JFrame frame = new JFrame(); 
     m_LogMgr=CMessageWindowStack.getInstance(); 
     m_LogMgr.setContainerFrame(frame); 
     frame.setVisible(true); 
     frame.setSize(500, 500); 


     for(int i=0;i<10000;++i){ 
      try { 
       Thread.sleep(0);//becomes unresponsive if sleep(0) 
      } catch (Exception e) { 
      } 
      m_LogMgr.printlnMsg(i+"-----------------------"); 
     } 

    } 


} 
+0

可能会有一些提示http://java-sl.com/JEditorPanePerformance.html 可以帮助 – StanislavL 2013-05-14 17:25:19

回答

3

你可能会需要使用的SwingWorker。首先加载基本HTML的JEditorPane。那么你需要publish每行数据。数据发布后,您需要将文本插入到编辑器窗格中。

基本思想是你不能一次创建一个完整的HTML字符串。

我从来没有能够真正理解如何使用动态更改HTML的JEditorPane。也许你可以使用JTextPane。它支持不同的字体和颜色,并且更容易动态更新。

+0

+1。 “SwingWorker”是这里的正确答案。睡觉几乎从来都不是正确的答案。 – wchargin 2013-05-14 15:36:10

0

以及 - 作为一个黑客,你可以尝试这样的事:

for(int i=0;i<10000;++i){ 
     try { 
      if(i%100 == 0) { 
       Thread.sleep(10);//becomes unresponsive if sleep(0) 
      } 
     } catch (Exception e) { 
     } 
     m_LogMgr.printlnMsg(i+"-----------------------"); 
    } 
+0

谢谢,但我正在寻找一些解决方案,只需要修改updateMessages。 – 2013-05-14 15:37:57

+0

然后解决方案是一个相当大的努力线程的建议在其他答案..我提供这个黑客,因为你似乎正在玩睡眠呼叫。 – Randy 2013-05-14 15:39:31

0

您可以尝试使用线程,并给予它最高的优先级。另外,您可以将-XmX2020选项添加到java.exe。

其他解决方案可能是如果您使用JTextArea而不是JEdiorPane。看起来你用HTML所做的一切就是设计字体。您可以使用JTextArea上的java.awt.Font属性来执行此操作。