2011-01-05 50 views
1

這是我在這個網站的第一個問題,雖然不是我第一次進入清除我的疑惑,真棒網頁。 :)DocumentListener減慢Document.setCharacterAttributes方法?

我正在寫一個Java程序,突出顯示JTextPane中的代碼,我正在改變高亮完成的方式。我使用JTabbedPane讓用戶同時編輯多個文件,並使用Timer執行文檔高亮顯示,現在我構建了一個高亮隊列,該隊列在單獨的線程中運行,並實現了一個DocumentListener隊列文件作爲變化發生。

但是我有一個非常大的問題,如果通過DocumentListener添加文檔,Highlight過程需要很長時間,而如果通過直接從JTextPane獲取文檔將其添加到主類中,它只需要一個幾毫秒。 我已經在我的代碼中執行了多個基準,並發現從DocumentListener添加文檔時需要執行很多時間的操作是Document.setCharacterAttributes()方法。

這裏是通過的DocumentListener將文檔添加方法:

// eventType: 0 - insertUpdate/1- removeUpdate 
private void queueChange(javax.swing.event.DocumentEvent e, int eventType){ 
    StyledDocument doc = (StyledDocument) e.getDocument(); 
    int changeLength = e.getLength(); 
    int changeOffset = e.getOffset(); 
    int length = doc.getLength(); 
    String title = (String) doc.getProperty("title"); 

    String text; 
    try { 
     text = doc.getText(0, length); 

     if (changeLength != 1) { 
      Element element = doc.getDefaultRootElement(); 
      int startLn = element.getElement(element.getElementIndex(changeOffset)).getStartOffset(); 
      int endLn = element.getElement(element.getElementIndex(changeOffset + changeLength)).getEndOffset() - 1; 

      Engine.addDocument(doc, startLn, endLn, title, text); 
     } else { 
      if(eventType == 1){ 
       changeOffset = changeOffset - changeLength; 
      } 
      int startLn = text.lastIndexOf("\n", changeOffset) + 1; 
      int endLn = text.indexOf("\n", changeOffset); 

      if (endLn < 0) { 
       if (length != startLn) { 
        endLn = length; 

        Engine.addDocument(doc, startLn, endLn, title, text); 
       } 
      } else if (startLn != endLn && startLn < endLn) { 
       Engine.addDocument(doc, startLn, endLn, title, text); 
      } 
     } 
    } catch (BadLocationException ex) { 
     Engine.crashEngine(); 
    } 
} 

如果我添加一個文件與2k行用這種方法,它需要〜1900毫秒以突出整個文檔,而如果我添加的文件通過使用插入符號聆聽方法來突出顯示隊列,它需要〜500 ms。

這裏是用來強調整個文檔時,他們正在加載插入符偵聽方法的一部分:

if (loadFile == true) { 
    isKey = false; 
    doc = edit[currentTab].Editor.getStyledDocument(); 
    try { 
     Highlight.addDocument(doc, 0, doc.getLength(), 
       Scripts.getTitleAt(currentTab), doc.getText(0, doc.getLength())); 
    } catch (BadLocationException ex) { 
     ex.printStackTrace(); 
    } 
    loadFile = false; 
} 

注:最亮/ Engine.addDocument()方法有五個參數:(StyledDocument中的DOC ,int start,int end,String tabTitle,String docText)。開始和結束兩者都表示需要突出顯示的區域。

我將不勝感激與此問題有關的任何幫助,因爲我一直在試圖解決它幾天,而且我在互聯網上找不到任何類似的東西。 :(

順便說一句,沒有人知道Document.setCharacterAttributes和Document.setParagraphAttributes之間的實際差異:P

回答

0

也許你有某種在你的代碼的遞歸導致該問題通過的DocumentEvent你應該。只需要擔心增加和刪除,你不必擔心變化,因爲這些屬性是變化的。

也許你添加了一些文本來安排突出顯示,但是當你改變文本的屬性時,你安排了另一個高亮顯示任務

+0

感謝您的回覆,但我忽略了changedUpdate方法,因爲用戶無法訪問文本屬性,因此在該方法觸發時沒有任何操作。 只有當insertUpdate或removeUpdate被觸發時,突出顯示纔會排隊,並且我使用的突出顯示方法通過設置Document的一部分的字符屬性來突出顯示文本,因此該方法不會插入更多文本。 – escabuchen 2011-01-05 07:10:35

0

你不能可以設置一個標誌,指出是用戶更改還是API更改。在Engine.addDocument()的開始處,將標誌設置爲API狀態,並在更改完成後將其重置。 在您的監聽器中檢查該標誌並跳過API中的更改。 您寫了「我使用通過設置文檔的一部分的字符屬性來突出顯示文本,因此該方法不會插入更多文本」。我不確定它不插入文字。例如。你有「這是一個粗體文本」,那麼你選擇「粗體」並將屬性更改爲粗體。原始元素被分開,並出現3個新元素。我沒有測試它,但它可能會調用insertUpdate()和removeUpdate()

沒有人知道Document.setCharacterAttributes和Document.setParagraphAttributes之間的實際區別嗎? 有段落和字符屬性。字符屬性是字體大小,家庭,風格,顏色。段落屬性是對齊,縮進,行間距。 其實段落是char元素的父母。

+0

我剛剛測試過,並且在執行高亮操作時,insertUpdate()和removeUpdate()永遠不會被調用。 我的猜測是,由於突出顯示是通過將屬性設置爲文本來執行的,所以每次調用Doc.setCharacterAttributes()時文檔都必須通知文檔偵聽器,而且這似乎很耗時。 我試過在執行高亮之前刪除了文檔偵聽器,但由於文檔的來源是文檔偵聽器,所以當我刪除DocListener時,對該文檔所做的更改沒有更新。 – escabuchen 2011-01-05 15:59:43