質問: (Graphics2D)g; int i=0; if(mode==1){ for(i=0;i
回答: コードを拝見すると「JBottonのアイコンや位置を変更することでその内容が画面に反映される」ことを利用してアニメーションを実現しようとしているように見えます。そうと仮定してコメントします。 コンポーネントの状態(位置・サイズ・アイコンなどの内容)を変更すると確かにそれは画面に反映されます。しかし「変更した時点で即座に反映されるのではない」という点に注意すべきです。状態の変更と画面反映は概ね次のような流れになると考えるとよいでしょう。(正確な反映タイミングは必ずしも以下のとおりとは限りませんがそれは重要ではなくワンクッション置いてから画面反映が行われる点がポイントです) 1. コンポーネントの状態を変更 この際に起こることは「コンポーネントの内容が画面へ未反映である=dirtyである」と記録されることだけです。これはまた直接・間接に「repaintを呼び出す」ということを引き起こしますが、repaintを呼び出しても画面へはすぐに反映されないと考えた方が無難だと思います。 2. 一旦Event Dispatch Loopへ戻る コンポーネントの状態を変更したら(and/or repaintを呼び出したら)特に何もせずにそのままEvent Dispatch Loopへおとなしく戻ります。 3. 再描画処理の起動 Event Dispatch Loopでは「ユーザーからの入力」や「再描画が必要なdirtyなコンポーネントが存在する」といった情報から適当なハンドラーメソッドが自動的に呼び出されます。本件の場合は再描画のためにpaint/paintComponentメソッドが呼び出され1で行った状態変更の結果が画面に反映されます。 ではどうアニメーションを実現するかといえば一般的には次のようにします。 * 一定時間ごとに起動されるコールバックでコンポーネントの状態を少しずつ変える Timerを使うと一定時間ごとに特定のコールバックをEDT上で呼び出してもらうことができます。そのコールバックの中で繰り返し起動される度にちょっとずつ違うコンポーネント状態へ変更してやります。 * 描画(paintComponent) 大抵の場合アニメーションをするからと言って再描画メソッドをオーバーライドする必要はないと言えます。そもそもpaintComponentの役割は「現在のコンポーネントの内容に従って画面へ描画する」ことなのでコンポーネントの状態変更はしないほうがよいでしょう。 以下は簡単な例です。 ``` class MyFrame extends JFrame { Timer timer; JButton button; MyFrame() { // Timerのセットアップ // (0.1秒ごとにonUpdateAnimationFrameを起動。これを無限に繰り返す) timer = new Timer(100, ev -> onUpdateAnimationFrame()); timer.setRepeats(true); ... } ... // アニメーション開始時に呼び出すべきメソッド void onStartButtonAnimation() { animationFrame = 0; timer.start(); } int animationFrame; // アニメーション中に0.1秒ごとに呼び出されるコールバック void onUpdateAnimationFrame() { // animationFrameに応じた位置やアイコンを設定 // ここでは状態を変更するだけであり再描画もここで起こると考えない方がよい。 updateButtonState(button, animationFrame++); if (animationFrame > 5) timer.stop(); // フレーム5まで変化させ終わったらタイマーを止める } } ```