2013-07-04 114 views
0

Qt :: QUndoCommand问题和可能的解决方案。QT:QUndocommand&实时编辑

我们正在开发3D编辑在Qt中的应用。

我们需要实现一个“操作堆栈”,它允许用户在他的操作中调用undo-redo。

我们使用QUndooStack和QUndoCommand Qt类。

该应用程序基于MVC模式,因此View(QGLWidget)知道如何绘制场景结构。

我们有滑块(QSlider)来转换/旋转/缩放3D对象(网格),我们需要实时显示转换效果。

例如,如果我选择了一个对象,并且正在移动“X Translation Slider”,我想在拖动滑块时看到沿着X轴移动的对象。 问题是要获得与操作堆栈一起工作的实时编辑。实际上,应该在堆栈上压入的“可撤销”操作是总滑块移动(从压制到释放滑块)。

我们发现了2种方式这样做的:

  1. 虽然我拖动滑块(在每一个的valueChanged信号) 转换应用到模型和QGLWidget来绘图更新 直每个滑块勾选后。在释放滑块时,必须将 命令压入堆栈。 QUADoStack在推送命令时自动调用 QUndoCommand :: redo()操作。为防止 该操作被执行两次(第一次授予 的实时效果,第二次在QUENDoStack :: push()调用中),在调用QUOToStack :: push()之前调用 将 应用于对象(从总滑块移动中获得),然后将命令压入堆栈。

  2. QUENDoStack尝试合并命令,当它们对调用QUndoCommand :: Id()具有相同结果 时。当我拖动滑块时(每个valueChanged信号在 处),会生成一个QUndoCommand,并立即将其压入堆栈,堆栈将它与顶部的 命令合并,如果它们具有相同的Id(),则堆栈调用 正在插入的命令的重做(),然后QGLWidget 更新和实时效果获得。

随着“命令”类的一个实例生成的每个滑块刻度第二个,而与第一个实时操作get的恢复只是推命令,并保持一致的状态。

什么解决方案在“良好的编程”方面更好?在性能方面哪个更好?

回答

3

我认为你正在寻找QUndoStack::beginMacro()QUndoStack::endMacro()

哪些可以使用,以便他们完成/未完成作为一个原子操作合并一系列命令在撤消堆栈。

+0

问题不在于如何去做,而是上面两种解决方案更好。 – Nicola

+1

你的两个解决方案看起来都过于复杂并且有点令人费解。我甚至很难说出你甚至想说什么。我也很困惑你为什么要在事物上调用redo(),同时把它们放在撤消堆栈上。如果您在用户开始滑动时只使用beginMacro(),并在完成滑动时使用endMacro(),则您的命令将由Qt的代码自动组合。没有自定义要求。 – Chris

0

Chris是正确的,您可以使用宏以及您提出的解决方案。但我不认为他对“过度复杂”的批评是公平的:Qt合并随着AND宏观机制是为你的目的而设计的。

我不担心任何解决方案的性能,直到您发现性能是一个问题。让它工作,然后测试性能,然后修复任何性能问题。直到你尝试过,是否产生了过多的命令(然后被合并)或逆向转换是性能问题,你无法知道。

另一种解决方案:在第一次打勾时,按下一个命令并保存对它的引用。在随后的滴答声中,更新命令并执行变换增量?

(有一个相关的问题,其中一个命令被按下,但用户取消了该操作,例如,如果用户拖动滑块,但是将鼠标释放到滑块外部?幻灯片是否被取消?搜索“事务性撤消命令“,它重新实现了重做,所以它在第一次被调用时不做任何事情,因为命令是堆叠的,并且有一个稍后调用的commit()或rollback()方法)。你的文章:当self.mergeWith(other)被调用时,Qt调用其他文件的重做方法,这从文档中不清楚)。