0

Qt::QUndoCommand の問題と可能な解決策。

Qt で 3D 編集のアプリケーションを開発しています。

ユーザーが自分の操作に対して元に戻す/やり直すことができるようにする「操作のスタック」を実装する必要があります。

QUndoCommand Qt クラスで QUndoStack を使用しています。

アプリケーションは MVC パターンに基づいているため、ビュー (QGLWidget) はシーン構造を描画する方法を認識しています。

3D オブジェクト (メッシュ) を移動/回転/スケーリングするためのスライダー (QSlider) があり、変換の効果をリアルタイムで表示する必要があります。

たとえば、オブジェクトを選択して「X Translation Slider」を動かしている場合、スライダーをドラッグしている間、オブジェクトが X 軸に沿って移動するのを見たいと思います。問題は、操作のスタックでリアルタイム編集を機能させることです。実際、スタックにプッシュする必要がある「元に戻す」操作は、スライダーの全移動 (スライダーを押してから離すまで) です。

これを行うには、次の 2 つの方法があります。

  1. スライダーを (すべての valueChanged シグナルで) ドラッグしている間、変換がモデルに適用され、QGLWidget はすべてのスライダー ティックの直後に更新されます。スライダーを放した時点で、コマンドをスタックにプッシュする必要があります。コマンドがプッシュされると、QUndoStack は自動的に QUndoCommand::redo() アクションを呼び出します。QUndoStack::push() の呼び出しの前に操作が 2 回実行されるのを防ぐために (1 回目はリアルタイム効果を付与するため、2 回目は QUndoStack::push() 呼び出しで)、逆変換がオブジェクト (スライダーの合計移動から取得) を取得し、コマンドをスタックにプッシュします。

  2. QUndoStack は、QUndoCommand::Id() の呼び出しの結果が同じ場合、コマンドをマージしようとします。スライダーをドラッグしている間 (valueChanged シグナルごとに) QUndoCommand が生成され、すぐにスタックにプッシュされます。同じ Id() がある場合、スタックはそれを上部のコマンドとマージし、スタックは redo( を呼び出します。 ) 挿入されているコマンドの場合、QGLWidget が更新され、リアルタイムの効果が得られます。

2 番目のものでは、"Command" クラスのインスタンスがスライダー ティックごとに生成されますが、最初のものでは、コマンドをプッシュして一貫した状態を維持するためだけにリアルタイム操作が元に戻されます。

「優れたプログラミング」に関してはどのソリューションが優れていますか?パフォーマンスに関してはどのソリューションが優れていますか?

4

2 に答える 2

3

私はあなたが探していると思いQUndoStack::beginMacro()ますQUndoStack::endMacro()

これを使用して、元に戻すスタック内の一連のコマンドをマージし、アトミック操作として実行/元に戻すことができます。

于 2013-07-04T18:10:08.870 に答える
1

クリスは正しいです。提案されたソリューションだけでなく、マクロも使用できます。しかし、「過度に複雑」に対する彼の批判は公正ではないと思います。Qt の mergeWith AND マクロ メカニズムは、あなたの目的を意図したものです。

パフォーマンスに問題があることがわかるまで、どのソリューションのパフォーマンスについても心配する必要はありません。動作させてからパフォーマンスをテストし、パフォーマンスの問題を修正します。過剰なコマンドの生成 (その後マージされる) または逆変換がパフォーマンスの問題であるかどうかは、試してみるまでわかりません。

別の解決策: 最初のティックでコマンドをプッシュし、それへの参照を保持します。後続のティックで、コマンドを更新し、変換のインクリメントを実行しますか?

(コマンドがプッシュされたが、ユーザーが操作をキャンセルした場合に関連する問題があります。たとえば、ユーザーがスライダーをドラッグし、スライダーの外でマウスを離した場合はどうなるでしょうか?スライドはキャンセルされますか?「トランザクション取り消しコマンド」を検索してください。コマンドがスタックされているため、最初に呼び出されたときに何もしないように再実装し、後で呼び出される commit() または rollback() メソッドを持っています。)

(あなたの投稿から何かを学びました: self.mergeWith(other) が呼び出されると、Qt は other の redo メソッドを呼び出します。ドキュメントからは明らかではありません。)

于 2013-08-08T16:19:56.880 に答える