答えはすでにJonasによって与えられています(Swingタイマーを使用)が、アニメーションが表示されない理由と、タイマーがこの問題の最善の解決策である理由を説明するのに役立つ場合があります。
別の塗り直しが表示されないのはなぜですか
あなたが呼ぶときJComponent#repaint
、JComponent
は塗り直されません。代わりに、特定のコンポーネントを再描画する非同期要求がEDTでスケジュールされます。多くの呼び出しを呼び出す場合repaint
、Swingはそれらの要求をグループ化し、コンポーネントを1回だけ再描画することを決定する場合があります。
Oracleのドキュメントでこれに関する公式のリファレンスをすぐに見つけられませんでした(Swingのペイントの記事では言及されていないようです)。私がこれを見つけた唯一の場所はこの記事のメモにありましたが、これはどこかに文書化されていると確信しています。
なぜTimer
最良のソリューションを使用しているのですか
アニメーションの場合、基本的に次のように言います。
私のキャラクターはミリ秒単位x
でピクセルを移動する必要がありますy
そして、できれば、画面上で滑らかなアニメーションを作成したいので、かなり頻繁に再描画する必要があります。あなたがそれを覚えているなら
- Swingコンポーネントとのすべての対話は、EDTで行われる必要があります(イベントディスパッチスレッド。詳細については、Swingでの同時実行の記事を参照してください)。
- EDTをブロックしないでください。UIがフリーズします。つまり、再ペイントが完了するまでEDTで「待機」できないか、再ペイントが発生しません。
- 再描画リクエストはグループ化できるため、再描画時間を呼び出しても、メソッドが時間も呼び出されると
x
は限りません。paint
x
この制限を克服するための解決策は、を使用することTimer
です。同じ例(画面上のキャラクターの移動)では、を使用しTimer
てキャラクターの位置を更新し、再描画をスケジュールできます。コードはEDTでトリガーされるためTimer
、Swingスレッドルールに違反することはありません。
次に、コンポーネントのpaintComponent
メソッドで、現在の場所にキャラクターをペイントします。これは、前の呼び出しと現在の呼び出しTimer
の間にトリガーされた回数に応じて、「前の場所+ 1」、または「前の場所+2」(または...)の場合があります。これにより、キャラクターの移動速度がシステムに依存しなくなります。アニメーションの滑らかさだけがシステムに依存します(グループ化される再描画リクエストの数など)。paint
paint
JonasがすでにリンクしているSwingチュートリアルには、より多くの情報が含まれていますTimer
。