2013-07-04 42 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調用其他文件的重做方法,這從文檔中不清楚)。