0

以前の (未回答の) 質問で述べたように、プログラムに埋め込むことができる画像エディターを作成しています。そこで、イメージ エディタには元に戻す機能とやり直し機能が必要だと判断しました。だから私はこのコードを書いた:

public Vector<Color[][]> undo = new Vector<Color[][]>();
size = 16;
public Color[][] chroma = new Color[size][size];
//These are variables

public void saveRevision(){
    System.out.println("Saving: " + current);
    undo.insertElementAt(chroma.clone(), current);
    current++;
    /*for (int i = 0; i < (undo.size()-1); i++) {
        if(i > current){
        undo.remove(i);
        }
    }*/
}

public void undo(){
    if(current > 0){
        System.out.println("Gathering: " + (current-1));
        current--;
        /*Color[][] c = undo.get(current);
        for (int i = 0; i < c.length; i++) {
            for (int j = 0; j < c[i].length; j++) {
                System.out.print(c[i][j]);
            }
            System.out.println();
        }*/
        /*for(int i = 0; i < size; i++){
            for(int j = 0; j < size; j++){
                chroma[i][j] = null;
            }
        }*/
        chroma = undo.get(current);
        repaint();
    }
}

public void redo(){
    if((undo.size()-1) > current){
        System.out.println("Gathering: " + (current+1));
        current++;
        for(int i = 0; i < size; i++){
            for(int j = 0; j < size; j++){
                chroma[i][j] = null;
            }
        }
        chroma = undo.get(current);
        repaint();
    }
}

問題は、すべてのクロマ リビジョンを持つベクターから配列内に書き込めないことです。ご覧のとおり、すべて試してみましたが、「chroma」変数は変更されていないようです。Em 私は何か間違ったことをしていますか?

言及するのを忘れていました: Undo と Redo は JButton を使用してトリガーされ、リビジョンはマウス ボタンが離されるたびに作成されます。

4

2 に答える 2

1

問題は、元に戻す/やり直すには、元に戻すキューに不変データが含まれている必要があることです。

これは、すべての変更 (変更のアトミック グループ) がchroma 新しい 2D 配列のコピーを必要とすることを意味します。高い。

解決策は、元に戻す/やり直しキューに変更アクションのみを保持することです。

Java には、 Action インターフェースを実装する AbstractAction があり、編集の例としてUndoManagerがあります。多分それについて少し研究をしてください。

(Vector も控えてください。ArrayList はコメントを与えません。)


もう少し詳しく説明します:

chroma[][]が現状です。元に戻す/やり直し機能の場合、この状態を以前のものに変更する必要があります。これで、前の瞬間に元に戻すことで、状態全体、 のコピーをすべての時点で保存できるようになりましたchroma。より良い方法は、2 つの状態間の変更を保存することです。したがって、アクションペアのみを保存するようchroma[47][11]に変更された場合:AB

undo: chroma[47][11] = A;
redo: chroma[47][11] = B;

この (より多くの労力を必要とする) 代替案は、多くの場合、より実用的です。

のコピーを保存するという、元の選択がより直接的であった可能性がありますchroma。次に、何らかのユーザーアクションによってクロマに割り当てても、保存された状態が変更されることはありません。コピーは不変 = 変更不可である必要があり、その内部状態は変更可能なものに依存しません。

したがって、コピーが必要な理由は次のとおりです。

Color[][] chroma = ...;
Color[][] falseCopied = chroma;
chroma[3][4] = c;
// Now also `falseCopied[3][4].equals(c)`.

実際のコピーを行うことができます:

public static Color copy(Color[][] grid) {
    Color[][] copied = new Color[grid.length][];
    for (int i = 0; i < grid.length; ++i) {
        copied[i] = Arrays,copyOf(grid[i], grid[i].length);
    }
    return copied;
}

ここでは、すべての Color 自体のコピーを作成する必要はありません。これは、Color が「不変」であるためです。つまり、その内部状態を変更することはできません。みたいなcolor.setBlue(23)ものは存在しません。

于 2015-02-21T10:57:27.183 に答える
0

Java コレクションのチュートリアルを見て、コードを再構築することをお勧めします。たとえば、Java Vector クラスは廃止され、非推奨と見なされます (また、Vector はスレッド セーフであり、JButton の使用から判断すると、おそらく EDT でこれを呼び出すため、その必要はありません)。また、低レベルの多次元配列を使用すると、本当に特定の (パフォーマンス) 要件がある場合に役立ちますが、シナリオではそうではないと思います。

高レベルの Java コレクション構造を使用して、目的を達成するためのはるかに簡単で読みやすい方法があります。

于 2015-02-21T09:55:43.000 に答える