2012-10-03 85 views
5

我想使用JEditorPane來顯示一些HTML文本。出於某種原因,我必須使用setText()方法。但是,這使得JEditorPane閃爍。原因是每次更新後editorPane.setText(msgBuffer);我必須將光標移到文檔末尾editorPane.setCaretPosition((editorPane.getDocument())。getLength() - 1) asI希望最近的文本行出現在文檔的底部。 我給你們看了整個代碼,讓你親自看到它。我見過很多關於使用document.insertString的建議,但是對於這個問題我必須使用不屬於我感興趣的個人屬性。 有什麼辦法可以讓這段代碼無閃爍地運行?使用jEditor.setText()在JEditorPane中顯示HTML使其閃爍

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

public class CMessageWindow { 

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

    private CMessageWindow() 
    { 
     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; }"); 
     styleSheet.addRule("."+ERROR+" {font: 10px monaco; color: #ff2222; background-color : #cccccc; }"); 

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

    { 
     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 void printErr(String sMessage){ 
     String sType = ERROR; 
     updateMessages(sMessage,sType); 
    } 

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

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

     for(int i=0;i<20;++i){ 
      m_LogMgr.printlnErr("MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"); 
     } 

     for(int i=0;i<150;++i){ 
      try { 
       Thread.sleep(20); 
      } catch (Exception e) { 
      } 
      m_LogMgr.printlnMsg("-----------------------"); 
     } 

    } 


} 

回答

5

您不應該修改EDT以外的UI組件。

如果您在內部添加了一個呼叫,例如您的updateMessages,以便更新發生在EDT上,則閃爍消失。

例如:

,你不應該在美國東部時間執行長時間運行的操作
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); 
      } 
     } 
    }); 
} 

注意,否則你會「鎖定」您的UI。

+0

或沒有任何變化可見GUI – mKorbel

0

如果你有一個長期運行的IO和更新的GUI後,您可以使用SwingWorker代替(見http://en.wikipedia.org/wiki/Event_dispatching_thread

SwingWorker<Document, Void> worker = new SwingWorker<Document, Void>() { 
    public Document doInBackground() throws IOException { 
     return loadXML(); // heavy task 
    } 

    public void done() { 
     try { 
      Document doc = get(); 
      display(doc); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
}; 
worker.execute();