首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >javax.swing.text.AbstractDocument$LeafElement包含无效的p0/p1值

javax.swing.text.AbstractDocument$LeafElement包含无效的p0/p1值
EN

Stack Overflow用户
提问于 2014-09-04 05:33:49
回答 3查看 155关注 0票数 0

我会提前为这方面的缺乏细节道歉,但我不确定这是如何造成的。

我们有一个扩展javax.swing.text.DefaultStyledDocument的XMLDocument

如果我们进行快速的撤销/重做调用(比如,按住ctrl+z或ctrl+shift+z),AWT EventQueue线程就会抛出异常:

代码语言:javascript
复制
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 Update线程调用的。

它所吐出的实际元素是:

代码语言:javascript
复制
[4] = {javax.swing.text.AbstractDocument$LeafElement@6621}"LeafElement(content) 223,217\n"
p0 = {javax.swing.text.GapContent$StickyPosition@6652}"223"
p1 = {javax.swing.text.GapContent$StickyPosition@6655}"217"
this$0 = {com.timetra.nms.client.gui.script.editor.document.XmlApiDocument@6211}
parent = {javax.swing.text.AbstractDocument$BranchElement@6585}"BranchElement(paragraph) 191,238\n"
attributes = {javax.swing.text.StyleContext$SmallAttributeSet@6656}"{family=Courier,size=12,foreground=java.awt.Color[r=0,g=0,b=0],}"
this$0 = {com.timetra.nms.client.gui.script.editor.document.XmlApiDocument@6211}

(取自intelliJ调试器)。

如你所见,p0和p1是不正确的。但是,这个元素不应该在那里,因为数组中的3和5个元素与范围匹配:

代码语言:javascript
复制
[3] = {javax.swing.text.AbstractDocument$LeafElement@6620}"LeafElement(content) 215,223\n"
[4] = {javax.swing.text.AbstractDocument$LeafElement@6621}"LeafElement(content) 223,217\n"
[5] = {javax.swing.text.AbstractDocument$LeafElement@6622}"LeafElement(content) 223,237\n"

我假设我缺少一个同步,或者一个SwingUtilities.runLater(...)调用,但我不知道它们放在哪里,我已经把它们放在我们使用的撤销/重做类中任何我能想到的地方。

编辑:

以下是将编辑内容添加到UndoManager的方式:

代码语言:javascript
复制
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上的一个函数引起的,该函数试图在undo/redo事件之后语法突出显示文本。我担心即使它在EventQueue上,它也不同步。对于触发这些事件的顺序,是否有优先级或其他顺序?

EN

回答 3

Stack Overflow用户

发布于 2014-09-04 08:19:26

您推断不正确同步的可能性是正确的。异常可能由于另一个线程上的错误Document更新而发生在EDT上。在最近的Java版本中,某些文本组件的某些methods不再被标记为线程安全。根据引用here的文章中的建议,查找违反EDT的情况。对于初始检查,CheckThreadViolationRepaintManager是更简单的方法。

票数 2
EN

Stack Overflow用户

发布于 2014-09-06 15:18:16

您必须将更改事件添加到UndoManager。在相反的情况下,文档结构被更改,但您尝试撤消旧结构。您可以在一个提示中合并多个合并请参阅java-sl.com/ UndoableEdits _undo_edits.html

票数 0
EN

Stack Overflow用户

发布于 2015-04-11 10:40:20

我想出了一个解决方案,在编辑后应用于文本框的语法突出显示的更新中添加一个计时器。如果文本框在200ms计时器内更新,则更新将排队,并在语法突出显示发生后应用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25654035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档