2014-09-03 37 views
0

由於缺乏特異性,我會提前道歉,但我不確定這是如何引起的。

我們有一個擴展javax.swing.text.DefaultStyledDocument中

如果我們做出迅速撤銷/重做調用(比如,按住Ctrl + Z或按Ctrl + Shift + Z)一爲XMLDocument,在AWT EventQueue的線程拋出一個例外:

javax.swing.text.BadLocationException: Length must be positive 
getText():810, AbstractDocument {javax.swing.text} 
getText():135, GlyphView {javax.swing.text} 
getSpan():60, GlyphPainter1 {javax.swing.text} 
getPreferredSpan():592, GlyphView {javax.swing.text} 
getPreferredSpan():732, FlowView$LogicalView {javax.swing.text} 
calculateMinorAxisRequirements():233, FlowView {javax.swing.text} 
calculateMinorAxisRequirements():724, ParagraphView {javax.swing.text} 
checkRequests():935, BoxView {javax.swing.text} 
getMinimumSpan():568, BoxView {javax.swing.text} 
calculateMinorAxisRequirements():903, BoxView {javax.swing.text} 
checkRequests():935, BoxView {javax.swing.text} 
setSpanOnAxis():343, BoxView {javax.swing.text} 
layout():708, BoxView {javax.swing.text} 
setSize():397, BoxView {javax.swing.text} 
setSize():1714, BasicTextUI$RootView {javax.swing.plaf.basic} 
modelToView():1046, BasicTextUI {javax.swing.plaf.basic} 
repaintNewCaret():1311, DefaultCaret {javax.swing.text} 
run():1290, DefaultCaret$1 {javax.swing.text} 
dispatch():312, InvocationEvent {java.awt.event} 
dispatchEventImpl():733, EventQueue {java.awt} 
access$200():103, EventQueue {java.awt} 
run():694, EventQueue$3 {java.awt} 
run():692, EventQueue$3 {java.awt} 
doPrivileged():-1, AccessController {java.security} 
doIntersectionPrivilege():76, ProtectionDomain$1 {java.security} 
dispatchEvent():703, EventQueue {java.awt} 
pumpOneEventForFilters():242, EventDispatchThread {java.awt} 
pumpEventsForFilter():161, EventDispatchThread {java.awt} 
pumpEventsForHierarchy():150, EventDispatchThread {java.awt} 
pumpEvents():146, EventDispatchThread {java.awt} 
pumpEvents():138, EventDispatchThread {java.awt} 
run():91, EventDispatchThread {java.awt} 

現在,顯然這是從AWT更新線程調用的。

它拋出了對實際元素是:

[4] = {[email protected]}"LeafElement(content) 223,217\n" 
p0 = {[email protected]}"223" 
p1 = {[email protected]}"217" 
this$0 = {c[email protected]6211} 
parent = {[email protected]}"BranchElement(paragraph) 191,238\n" 
attributes = {[email protected]}"{family=Courier,size=12,foreground=java.awt.Color[r=0,g=0,b=0],}" 
this$0 = {c[email protected]6211} 

(來自的IntelliJ調試器獲取)。

您可以看到p0和p1不正確。而且,該元件不應該存在由於[3]和[5]的數組中的元素相匹配的範圍內:

[3] = {[email protected]}"LeafElement(content) 215,223\n" 
[4] = {[email protected]}"LeafElement(content) 223,217\n" 
[5] = {[email protected]}"LeafElement(content) 223,237\n" 

我假設我缺少的同步,或SwingUtilities.runLater( ...)的調用,但我不知道在哪裏,我已經把它們放在了我們可以在我們使用的撤消/重做類中想到的地方。

編輯:

這是編輯是如何被添加到的UndoManager:

public void undoableEditHappened(final UndoableEditEvent ev) 
    { 
     UndoableEdit edit = ev.getEdit(); 
     // Include this method to ignore syntax changes 
     // To reduce memory consumption, do this check before adding runnable. 
     if (edit instanceof AbstractDocument.DefaultDocumentEvent && 
      ((AbstractDocument.DefaultDocumentEvent) edit).getType() == 
       AbstractDocument.DefaultDocumentEvent.EventType.CHANGE) 
     { 
      return; 
     } 

     try { 
      UndoableEdit temp = ev.getEdit(); 
      undoManager.addEdit(temp); 
      undoAction.updateState(); 
      redoAction.updateState(); 
      setChanged(true); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

編輯2:我發現大部分的我看到了一個功能,就是對的invokeLater是造成問題()runnable,它試圖在撤消/重做事件之後語法突出顯示文本。我擔心即使它在EventQueue上,它也不會同步。是否有優先順序或這些事件被解僱的順序?

+0

沒有人可以幫你沒有看到你的代碼,我懷疑這是時間太長,張貼在這裏。您將不得不設置一個異常斷點並嘗試在該行爲中捕獲它。 – 2014-09-03 21:41:37

+0

我只能從AWT EventQueue線程獲取異常,這就是我獲取上面發佈的信息的地方,沒有其他異常拋出。 我知道這是一個長鏡頭,沒有明顯的測試用例,我的工作,看看我是否可以重新創建它(我工作的一個大型舊一段代碼,沒有人知道)。 我在找的是指針。 – 2014-09-03 22:14:37

+0

您可以嘗試在SwingUtilities.invokeLater()中包裝所有撤銷/重做調用。還有一點是檢查UndoableEdits的存儲方式。他們是否有DOM結構的副本或對結構的引用。複製更安全 – StanislavL 2014-09-04 05:29:30

回答

2

你是正確的推斷錯誤同步的可能性。由於在另一個線程上錯誤Document更新,可能會在EDT上發生異常。某些文本組件的某些methods不再是在最近的Java版本中標記爲線程安全。按照引用的here文章的建議,尋找違反美國東部時間表的規定。對於初始檢查,CheckThreadViolationRepaintManager是更簡單的方法。

+0

我首先使用了CheckThreadViolationRepaintManager方法,但是這並沒有顯示任何內容,所以我使用方面的路線,發現有幾個地方是我們的代碼不是線程安全的,但沒有出現在文檔區域。 – 2014-09-04 18:33:03

+0

對不起,它沒有氾濫;我會遵循@StanislavL關於你的'UndoableEditEvent'處理程序。 – trashgod 2014-09-05 16:23:06

0

您必須將更改事件添加到UndoManager。在相反的情況下,文檔結構會發生變化,但您嘗試使用舊結構進行撤消。你可以合併多個UndoableEdits在一個看到java-sl.com/tip_merge_undo_edits.html

+0

對不起,代碼沒有寫的清楚,我會更新它,因爲撤消實際上是撤消管理器。 – 2014-09-09 14:56:58

0

我找出了一個解決方案,增加了一個計時器的語法高亮更新,在編輯後應用於文本框。如果文本框在200ms定時器內更新,則更新在發生語法突出顯示後排隊並應用。