在不向撤消堆栈添加撤消命令的情况下更改 QTextEdit

Posted

技术标签:

【中文标题】在不向撤消堆栈添加撤消命令的情况下更改 QTextEdit【英文标题】:Making changes to a QTextEdit without adding an undo command to the undo stack 【发布时间】:2014-11-24 20:07:58 【问题描述】:

我正在寻找一种方法来更改QTextEditQTextCharFormatQTextBlock 而不触发添加撤消命令。让我解释一下:

QTextBlockQTextCharFormat 可以使用QTextCursor::setBlockCharFormat() 方法轻松更改。假设我们有一个名为myTextEditQTextEdit,其可见光标在我们要更改的文本块内,我们可以像这样更改文本块的QTextCharFormat

text_cursor = myTextEdit.textCursor()
text_cursor.setBlockCharFormat(someNewCharFormat)

上面的代码可以正常工作,但它也会在myTextEdit undo 堆栈中添加一个撤消命令。出于我自己的目的,我希望能够更改 QTextBlockQTextCharFormat而不向 QTextEdit 的撤消堆栈添加撤消命令。

我考虑使用QTextDocument::setUndoRedoEnabled() 方法暂时禁用撤消/重做系统,但该方法也会清除撤消堆栈,我不想这样做。我还寻找其他方法来更改撤消/重做系统的行为方式,但我还没有找到一种方法让它暂时忽略更改。我只是想对QTextEdit 进行更改,而无需撤消/重做系统注册更改。

感谢任何提示或建议。谢谢!

【问题讨论】:

我认为你可能不走运,请参阅this qt-interest thread(有点旧,但它很好地总结了问题)。 【参考方案1】:

您必须将此与之前的修改分组。很简单,你必须用beginEditBlockendEditBlock 包围进行此修改的代码。见documentation。

text_cursor = myTextEdit.textCursor()
text_cursor.beginEditBlock()
text_cursor.setCharFormat(someOtherCharFormat) # some previous modification
text_cursor.setBlockCharFormat(someNewCharFormat)
text_cursor.endEditBlock()

这样,您将针对任何复杂的修改为撤消堆栈进行一次提交。

【讨论】:

嗨马雷克。感谢您的建议!不幸的是,这个解决方案不能满足我的需要。我真的需要根本没有添加撤消命令。我需要这个的原因是我正在尝试扩展撤消/重做系统以跟踪和更改默认情况下不跟踪的整个程序的属性。这意味着,当撤消操作时,我正在执行可以被视为撤消操作一部分的附加代码。在我的例子中,setBlockCharFormat() 方法将作为撤消的一部分运行,因此不应将撤消命令添加到堆栈中。 所以尝试undo 然后在编辑块redo 中进行更改。 beginEditBlock() 正是将许多操作折叠成一个撤消/重做步骤的原因。这很难找到。谢谢!我们正要重构 QTextDocument 以使用 QUndoStack。这为我们节省了 1 周的工作时间。 ?【参考方案2】:

joinPreviousBlock() 应该可以解决问题:

cursor = self.textCursor()
cursor.joinPreviousEditBlock()
cursor.setPosition(start, QTextCursor.MoveAnchor)
cursor.setPosition(end, QTextCursor.KeepAnchor)
cursor.setCharFormat(fmt)
cursor.endEditBlock()

【讨论】:

【参考方案3】:

您应该使用QSyntaxHighlighter。对其进行扩展并实现highlightBlock func,并在其中调用setFormat 以更改格式而不进行撤消/重做堆栈。详情请参阅documentation。

如果你觉得 QSyntaxHighlighter 不是你想要的,你可以使用QTextLayout。它是低级 api,它的setAdditionalFormats func 不会做任何撤消堆栈。

range1 = QTextLayout.FormatRange()
range1.start = 0
range1.length = 10
range1.format = QTextCharFormat()
# additional ranges here...
textBlock.layout().setAdditionalFormats([range1, ...])

这也用在QSyntaxHighlighter内部。

【讨论】:

以上是关于在不向撤消堆栈添加撤消命令的情况下更改 QTextEdit的主要内容,如果未能解决你的问题,请参考以下文章

如何撤消 Mercurial 中所有添加的文件

在 ACE 编辑器中重置撤消堆栈

使用 QUndoCommand 的子级/父级推送多个命令以一次撤消堆栈

如何撤消上一个添加迁移命令?

如何在不向用户显示堆栈跟踪的情况下处理 servlet 过滤器中的错误状态?

核心数据保存更改撤消