Qt:如何正确地将撤销框架与QGraphicsScene集成

7
我正在编写一个基于QGraphicsScene画布的Qt应用程序,并在其上移动形状。我正在尝试集成撤销-重做功能。对于大多数函数,如创建和删除形状,在QGraphicsScene本身上实现它们是相当简单的。但是,我希望元素可以移动,并且该移动可以撤销。目前,我正在使用场景上的橡皮筋拖动模式以及项目上的ItemIsSelectable和ItemIsMovable标志。问题在于似乎没有好的地方创建QUndoCommand来代表形状运动。如果我在QGraphicsScene :: itemChange方法中执行此操作,则选择和移动两个或更多形状会导致不同对象的单独撤消命令交错,因此无法合并,从而导致撤消时出现意外行为。我没有看到任何在其项移动时调用QGraphicsScene的事件,所以我有点困惑。
我预见的最坏情况是,在我的自定义QGraphicsItem对象上禁用ItemIsMovable标志,并完全在QGraphicsScene鼠标事件中处理移动,但是重新实现该功能似乎非常复杂(我检查了Qt在内部处理的代码量相当大,例如当同时选择一个对象及其某些子级时的复杂情况)。这似乎是撤消堆栈最显然的用例(非常之一,以至于撤消框架的示例程序是一个类似于我的QGraphicsScene程序,但没有多个对象移动支持),因此似乎很奇怪没有内置的方法可以在不重新实现核心功能的情况下完成它。还有人有任何见解或示例程序吗?
1个回答

7
我认为我以一种有些hackish的方式解决了这个问题。我给我的自定义形状添加了一个preMovePoint属性,并在QGraphicsScenemousePressedEvent中将每个选定形状的preMovePoint设置为其各自当前位置,在mouseReleaseEvent中,根据每个形状的preMovePoint和当前pos创建一个组合移动命令。如果有更好的方法,我还是很感兴趣的。

1
我想到了一个类似的 hackish 修复方法,涉及每个 QGraphicsItem 中的先前位置堆栈,然后将更改的项推送到撤消堆栈中。虽然很丑陋,但它确实有效。感谢提问和回答。 - Freedom_Ben
1
我不会说这很hackish,因为这是在官方Qt示例中实现的方式:https://doc.qt.io/qt-5/qtwidgets-tools-undoframework-example.html - Kaaf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接