4

コースのデモ用に設計された単純な Java Swing アプリケーションを作成しています。このプログラムの目的は、再帰的手法 (具体的には、迷路の再帰的解法) の進行状況を視覚化することです。再帰メソッドの実行時に JComponent の外観を更新できるようにしたいので、Swing の観点からは、アニメーションの通常のメソッドである Timer クラスから更新を個別にトリガーすることはできません。

私が最初に考えたのは、ビジュアライゼーションを再描画したいときはいつでも repaint() を呼び出すことだけでした。しかし、再帰メソッド自体は JButton のイベント ハンドラで呼び出されます。つまり、repaint() へのすべての呼び出しは、イベント ハンドラが終了するまで遅延されます。アニメーションの最後のフレームしか表示されません。次のように、代わりに update() を呼び出すと、すぐに描画が行われることがわかりました。

getRootPane().getContentPane().update(getGraphics());
try {
    Thread.sleep(25);
} catch (Exception e) {
}

アニメーションがちらつくことを除いて、これはほとんど機能します。Swing がダブル バッファリングされていることは知っていますが、どうやら getGraphics はバック バッファではなくアクティブ バッファを提供するようです。バック バッファにアクセスできるメソッドが見当たりません。

そこで、再帰の途中でコンポーネントを再描画し、ちらつきのないアニメーションを提供できるソリューションを探しています。イベント ハンドラーの実行中に組み込みのダブル バッファリングを有効にする方法はありますか? 独自のバッファリング システムを実装したほうがよいでしょうか? または、私がやろうとしていることは、Swing では不可能/お勧めですか?

(最後に、これは私の最初の投稿です。良い質問を書こうとしましたが、何か不足している場合はお知らせください。次回はもっとうまくやれるように努めます。ありがとう!)

4

2 に答える 2

2

まず、 Event Dispatch Thread で実行時間の長いアクションを実行するべきではありません。これがアニメーションがちらつく理由の 1 つだと思います。

そのため、ボタンを押したときに再帰メソッドを実行するスレッドを開始することをお勧めします (そして、作業が完了するまで非アクティブ化することもできます)。

アニメーションをレンダリングするにはmyComponent.repaint()、再帰メソッド内から呼び出すか、基本的に次のように見える Swing Timer を開始します (@mKorbel に感謝します)。

ActionListener repaintTrigger = new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
          myComponent.repaint();
      }
};
new Timer(25, repaintTrigger).start();

再帰メソッドはおそらく Swing コンポーネントについて何も知らないはずなので、後者のアプローチをお勧めします (「ProgressListener」などを介して分離しない限り)。

単なる初心者ではないように思われるので、何をすべきかについてヒントをいくつか示しました。さらに入力が必要な場合は、お気軽にお問い合わせください。

于 2013-04-02T23:34:16.447 に答える
0

これが実際に機能するかどうかはわかりませんが。マルチスレッド化し、再帰をグラフィックスから分離しようとします。これがJavaで機能するかどうかはわかりませんが、C#では機能しました。

于 2013-04-02T23:27:32.333 に答える