18

元に戻すをサポートするペイント プログラムを作成する方法を調べていますが、おそらくコマンド パターンが必要であることがわかります。誰かが簡単な答えや確認を提供してくれることを願っています。

基本的に、コマンドを元に戻す機能を具体化する場合、たとえば画面に塗りつぶされた円をスタンプする場合、円がメモリにカバーするフレーム バッファーをこのコマンド オブジェクトに本質的にコピーする必要があるということですか? たとえば、ランダムなピクセル色の束をスタンプするなど、元に戻すことができる他の方法はありません。

1 つのアプローチは、前方アクションを追跡するだけであり、元に戻す操作が実行されると、ステップ 1 から開始して元に戻す前のステップに前方描画するだけであると聞いたことがありますが、大規模なアクションをサポートする場合、これは実行不可能に思えます。スタックを元に戻します。

おそらく、解決策は、15 ~ 20 アクションごとのビットマップを保持し、最後の「保存」転送から開始する間の何かです。

この場合、コマンドでバッファの四角形を保存するか、すべてのアクションをやり直すか、または私が完全に見逃した何かについて、誰かが洞察を提供できますか?

更新: 良い反応がたくさんあります。みんな、ありがとう。私が読んでいることから、Nアクションごとにバッファを保存し、ユーザーが元に戻すコマンドを発行すると、最後に保存されたバッファからすべてのコマンドをやり直すことでこれにアプローチすると考えています。N を可能な限り高い値に微調整することはできますが、(メモリ使用量を最小限に抑えるために) レスポンシブな元に戻す必要があるというユーザー エクスペリエンスを著しく低下させることはありません。これはそれほど悪くないので、1 つのフレームでかなりの数のアクションを実行することで逃げることができます。願わくば、このアプローチにより、他の方向に切り替えるかどうかをすばやく判断し、代わりにそれを必要とするアクションのために以前の状態のビットマップ四角形を保存することができます.

4

5 に答える 5

10

まず、過剰な設計に注意してください。アプリが複雑ではなく、画像が小さい場合は、「すべてを保存するだけ」が迅速で安価で実現可能であることに気付くかもしれません。しかし、そうではないと仮定すると:

元に戻すたびにステップ 1 からキャンバス全体を再描画することは現実的ではないことは間違いありません。ペイント プログラムが非常に単純でない限り、一部の操作には時間がかかりすぎます。また、無限の元に戻すバッファーはおそらく必要ありません (保存するのに非常に多くのスペースを消費する可能性があります)。

アート プログラムが複雑な場合は、さまざまな操作に対処するために、実際にはハイブリッド アプローチから始めます。フレームバッファを頻繁に保存し(あなたが提案する15〜20コマンドごとに問題ないようです。10から始めて、機能するようになったら調整するかもしれません)、最後の保存から先に進みます。ただし、「15 回ごとの操作」を厳格にしないでください。経験則をいくつか追加すると、ユーザーにとってより流動的に見える可能性があります。

たとえば、時間のかかる操作や元に戻すのが難しい操作では、常に新しいセーブ ポイントが作成される可能性があります。
- キャンバスのサイズ変更 (トリミングなど)
- 任意の保存。(「保存したばかり」は、ユーザーが元に戻す可能性が非常に高い場所です。)
- 非常に時間がかかる操作は、操作の前ではなく、後に新しいセーブポイントを作成する必要があります。つまり、元に戻すためにバッファを保存する次の操作にフラグを立てる必要があります。(なぜですか? op に 30 秒かかる場合、その後のスタック内のすべての取り消しにさらに 30 秒以上かかることは望ましくありません。)
- 逆に、簡単に実行できる数学的なネガを持つ操作や、(フォトネガのような) 自己反転する操作は、フレーム バッファーを保存する必要がなく、次の保存にカウントされません。

これらはすべて、レイヤーの問題を除外しています。プログラムにそれらがある場合は、変更されたレイヤーのみを保存するだけで明らかに十分です。

ただし、間違いなく私の最優先の提案は次のとおりです。使用する方法に関係なく、実行した最新の操作のために常にフレーム バッファーを保存する必要があります。「おっと、そうではありませんでした」が元に戻す理由として最も可能性が高いため、常に undo-one-step が応答するようにする必要があります。保持していない場合は、次のコマンドの実行後にこのバッファーを破棄できます。

また、1 つのアトミックな元に戻す操作を構成するものも考慮する必要があります。(たとえば、1 つのブラシ ツールを使用した一連のストロークは 1 回の操作ですか、それとも複数回の操作ですか? どちらにも長所と短所があります。)

于 2010-10-15T17:55:34.787 に答える
3

おそらく、解決策は、15 ~ 20 アクションごとのビットマップを保持し、最後の「保存」転送から開始する間の何かです。

私はこのようなもので行きます。いずれにせよ、コマンド スタックをある時点でバインドする必要があるため、ユーザーが空にする場合は開始点が必要になります。

とにかくスタックからコマンドをドロップする必要があるため、境界に達したときにバッファを保存し、それをセーブポイントとして使用することができます。基本的に、セーブ ポイント バッファはドロップされたアクションの表現であるため、元に戻すスタックからアクションをドロップするときは、それらをそのバッファに書き込むだけです。

于 2010-10-15T17:34:50.730 に答える
2

1つのアプローチは、前方アクションを追跡することであり、元に戻すが実行されると、ステップ1から開始して、元に戻す前のステップに前方に描画するだけだと聞きました

これはあまり良い考えではありません。ユーザーは通常、最近のいくつかのアクションのみを元に戻し、それが高速であることを期待しているため、すべてを最初からやり直すよりも、すぐに元に戻せる方が適切です。

この場合、コマンドでバッファの四角形を保存する、すべてのアクションをやり直す、または私が完全に見逃したもののいずれかである、この場合の典型的な受け入れられたアプローチについて誰かが洞察を提供できますか?

すべてのコマンドを同じ方法で保存する必要はありません。操作の種類に応じて、次のような 1 つ以上の手法を使用できます。

  • 通常、描画/ペイント操作は直接元に戻すことができないため、元のイメージ コンテンツを保存するしかありません。ただし、画像全体ではなく変更された部分のみを保存することで、容量を節約できます。

  • 色の反転などの一部の操作は本質的に反転可能であるため、そのような場合は、操作のタイプを元に戻すスタックに格納するだけでよく、どちらの方向にも操作を再生できます。

于 2010-10-15T17:55:36.543 に答える
1

おそらく巨大なビットマップを描画しないのであれば、あなたのアプローチはまったく問題ないようです。

さらに単純化するには、画像全体をディスクの tmp ディレクトリに書き込み、ユーザーにとってどのようになるかを確認します。

最初から過度に設計しないでください。対処する必要がある他の問題があることは間違いありません。

于 2010-10-15T17:39:15.553 に答える
0

私の理解では、元に戻す/やり直しの種類のシステムを実装するためのコマンド パターンは、それらのアクションの実際の結果ではなく、アクションをスタックに記録するだけです (それらは順番に再作成/削除されるため)。あなたはこれをほのめかしたと思いますが、大規模な元に戻すスタックには実行不可能だと考えていると言いました。もっと具体的に言えますか?それは可能だと思います。

于 2010-10-15T17:35:21.863 に答える