我尝试创建from(incomingQueue)
.routeId("Incoming")
.choice()
.when(header("key").isEqualTo("a"))
.to("seda:A")
.when(header("key").isEqualTo("b"))
.to("seda:B")
;
from("seda:A")
.routeId("A")
.process(processor);
from("seda:B")
.routeId("B")
.process(processor);
的子类,表示一个或多个QUndoCommand
的移动。如果一次移动多个项目(首先选择它们),这应该在QGraphicsItem
中表示为单个命令。
由于QUndoStack
已经实现了整个移动逻辑(包括选择),我不确定创建撤销命令的最佳位置是什么。
Qt子类QGraphicsScene
提供的undoframework
示例,并覆盖QGraphicsScene
/ mousePressEvent()
以执行一些手动命中测试。这真的是要走的路吗?
我担心这种方法可能会遗漏一些特殊情况,使得生成的撤消命令不能完全反映内部Qt实现所执行的完全相同的移动。例如,有些项可能会设置mouseReleaseEvent()
标记。此外,当一次移动多个项目时,最好只存储增量移动而不是旧位置和新位置。
如果您能提供一些简短的示例代码/草图以供澄清,那将会很棒。
答案 0 :(得分:2)
我个人会包装并封装QGraphicsScene
并在那里实现撤消/重做的东西。这允许定义您自己的更清洁的界面,不会出现您不需要的所有功能的混乱。如果将来出现这样的需求,它还可以更容易地将QGraphicsScene
替换为另一个API,并使您的核心内容更具可移植性。
Qt中的许多高级课程,尤其是图形专业的高级课程,并不完全是我称之为“前沿”的课程,这同样适用于Qt为他们提供的基本实例。有几个使用Qt的专业图形应用程序,但没有一个使用像QGraphicsScene
这样的东西。我想这也是我之所以使用Qt从我自己的经验中推断出来的原因 - 它可能是一个很大的框架,有很多缺少的东西,还有很多东西不能真正起作用人们对专业软件的期望,甚至是这种工作流程中的共同逻辑。 Qt是由非常优秀的程序员开发的,但似乎他们没有经验丰富的实际图形应用程序工作流程来为他们提供建议。
专注于具有所需功能的包装器,并使其与QGraphicsScene
一起使用,而不是直接使用它。这样你错过了一些东西的机会就会减少,你的设计也会更加独立,更清洁。这同样适用于撤销API,也不觉得有必要使用Qt,我自己已经尝试过并最终实现了我自己的,因为我发现Qt提供的那个相当“僵硬”。
在一次移动多个项目的情况下 - 是的,这应该创建一个撤消条目,这将撤消选择组的移动,该选择组将包含所有选定的项目。无论您是使用三角洲还是位置 - 这完全取决于您。移动多个选定项目时,delta确实更有意义,因为选择组实际上不是具有位置的项目。
另一个考虑因素,如果您打算在不同的会话中保持历史记录持久性 - 您不能依赖指针,因为每次运行应用程序时这些都是任意的。我的策略是实现一个唯一的整数ID和一个关联注册表,它存储每个项目的id和指针。然后使用历史记录的ID,它将在内部映射到实际项目的指针。