Qt :: QUndoCommand问题和可能的解决方案。
我们正在开发Qt中的3D编辑应用程序。
我们需要实现一个“操作堆栈”,允许用户在其操作上调用undo-redo。
我们正在使用QUndoStack和QUndoCommand Qt类。
应用程序基于MVC模式,因此View(QGLWidget)知道如何绘制场景结构。
我们有滑块(QSlider)来平移/旋转/缩放3D对象(网格物体),我们需要实时显示变换的效果。
例如,如果我选择了一个对象并且我正在移动“X平移滑块”,我想看到当我拖动滑块时对象沿着X轴移动。 问题是让实时编辑与堆栈操作一起工作。事实上,应该被推到堆叠上的“可撤销”操作是滑块的总移动(从压力到滑块的释放)。
我们找到了两种方法:
当我拖动滑块(在每个valueChanged信号处)时 转换应用于模型和QGLWidget更新 每个滑块勾选后直接。在滑块的释放 必须将命令推入堆栈中。 QUndoStack会自动调用 按下命令时的QUndoCommand :: redo()操作。阻止 要执行两次的操作(第一次授予 实时效果,第二次在QUndoStack :: push()调用)之前 调用QUndoStack :: push()应用逆变换 到对象(从总滑块运动中获得)然后我 将命令推送到堆栈。
当QundoStack具有相同的结果时,它会尝试合并命令 从调用QUndoCommand :: Id()。当我拖动滑块时(at 每个valueChanged信号)生成一个QUndoCommand 立即推入堆栈,堆栈与它合并 如果它们具有相同的Id(),则在顶部命令,然后堆栈调用 正在插入的命令的redo(),然后是QGLWidget 获得更新和实时效果。
对于第二个,每个滑块滴答都会生成一个“Command”类的实例,而第一个实例操作则会恢复实时操作,只是为了推送命令并保持一致状态。
在“良好的编程”方面哪种解决方案更好?在性能方面哪些更好?
答案 0 :(得分:3)
我认为您正在寻找QUndoStack::beginMacro()
和QUndoStack::endMacro()
可用于合并撤消堆栈中的一系列命令,以便它们作为原子操作完成/撤消。
答案 1 :(得分:0)
Chris是正确的,您可以使用宏以及您提出的解决方案。但我并不认为他对“过于复杂”的批评是公平的:Qt mergeWith AND宏机制是出于你的目的。
在您发现性能出现问题之前,我不担心任何解决方案的性能。让它工作,然后测试性能,然后解决任何性能问题。在尝试之前,您无法知道生成过多命令(然后合并)或逆转换是否是性能问题。
另一个解决方案:在第一个刻度线上,按下命令并保持对它的引用。在后续滴答中,更新命令并执行转换增量?
(有一个相关的问题,即推送命令但是用户取消了操作。例如,如果用户拖动滑块,但是将滑块释放到滑块外?幻灯片是否取消?搜索“事务撤消”命令“。它重新实现重做,以便在命令堆叠时第一次调用它时不执行任何操作,并且具有稍后调用的commit()或rollback()方法。)
(我从你的帖子中学到了一些东西:当调用self.mergeWith(other)时,Qt会调用其他的redo方法。这在文档中并不清楚。)