2014-09-03 2 views
0

Я заранее извинюсь за отсутствие специфики в этом, но я не уверен, как это вызвано.

У нас есть XMLDocument, расширяющий javax.swing.text.DefaultStyledDocument

Если мы делаем быстрый откат/повтор вызовов (скажем, удерживая Ctrl + Z или Ctrl + Shift + Z), поток 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 (...), но я понятия не имею, где, я помещал их везде, о которых я могу думать в классах Undo/Redo, которые мы используем.

Edit:

Это как редактирование добавляются в 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(); 
     } 
    } 

Edit 2: Я нашел большинство вопросов, которые я видел, были вызваны функции, на invokeLater(), который пытается синтаксис выделить текст после события отмены/повтора. Я обеспокоен тем, что хотя это событие EventQueue не синхронизировано. Есть ли порядок приоритетов или что-то для порядка, в котором эти события запущены?

+0

Никто не может помочь вам, не увидев ваш код, и я подозреваю, что слишком поздно публиковать здесь. Вам нужно будет установить контрольную точку исключения и попытаться поймать ее в действии. –

+0

Я могу получить исключение только из потока AWT EventQueue, и именно там я получил информацию, которую я разместил выше, другого исключения не было. Я знаю, что это длинный снимок без отдельного теста, я работаю над тем, могу ли я его воссоздать (я работаю над массово старым фрагментом кода, о котором никто не знает). Что я ищу, это указатели. –

+0

Вы можете попробовать обернуть все вызовы отмены/повтора в SwingUtilities.invokeLater(). Еще один момент - проверить, как хранятся UndoableEdits. У них есть копия структуры DOM или ссылки на структуру. Скопировать безопаснее – StanislavL

ответ

2

Вы можете указать неверную синхронизацию. Исключение может возникнуть в EDT из-за ошибки переполнения Document в другом потоке. Некоторыми methods определенных текстовых компонентов являются уже не, отмеченные как потокобезопасные в последних версиях Java. Ищите нарушения EDT, как это предлагается в цитированных статьях here. Для первоначальной проверки CheckThreadViolationRepaintManager - это более простой подход.

+0

Сначала я использовал метод CheckThreadViolationRepaintManager, но это ничего не показывало, поэтому я пошел с маршрутом аспект и нашел несколько мест, поскольку наш код не был потокобезопасным, но ничего не появилось в области с документом. –

+0

Простите, что не вышло; Я отложу @StanislavL на ваш обработчик 'UndoableEditEvent'. – trashgod

0

Вы должны добавить изменения в UndoManager. В противном случае структура документа изменяется, но вы пытаетесь отменить ее со старой структурой. Вы можете объединить несколько UndoableEdits в одном виде. Java-sl.com/tip_merge_undo_edits.html

+0

Извините, код не был написан четко, я обновлю его, так как undo на самом деле является undoManager. –

0

Я разработал решение о добавлении таймера к обновлению подсветки синтаксиса, которое было применено к текстовому полю после редактирования. Если текстовое поле обновляется в течение 200 мс, обновление ставится в очередь и применяется после выделения синтаксиса.

Смежные вопросы