1

私の質問は、repaint() をメソッドから、より具体的には actionlistener から実行したときに適切に動作させる方法についてです。私の要点を説明すると、最初の go() から実行されたときの moveIt() メソッドは、予想どおり repaint() を呼び出し、円のスライドが表示されます。ボタン ActionListener から moveIt() が呼び出されると、円は開始位置から終了位置にジャンプします。repaint() の呼び出しの前と repaint() 内に println ステートメントを含めました。repaint() が起動時に 10 回呼び出され、ボタンが押されたときに 1 回だけ呼び出されることがわかります。- ご協力ありがとうございます。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SimpleAnimation {
int x=70;
int y=70;
MyDrawPanel drawPanel;

public static void main(String[] args) {
    SimpleAnimation gui = new SimpleAnimation();
    gui.go();
}
public void go(){
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    drawPanel = new MyDrawPanel();
    JButton button = new JButton("Move It");
    frame.getContentPane().add(BorderLayout.NORTH, button);
    frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
    button.addActionListener(new ButtonListener());
    //frame.getContentPane().add(drawPanel);
    frame.setSize(300,300);
    frame.setVisible(true);
    // frame.pack();  Tried it with frame.pack with same result.
    moveIt();
}//close go()
public void moveIt(){
    for (int i=0; i<10; i++){
            x++;
            y++;
            drawPanel.revalidate();
            System.out.println("before repaint"); //for debugging
            drawPanel.repaint();            
        try{
            Thread.sleep(50);
        }catch (Exception e){}
    }
}//close moveIt()
class ButtonListener implements ActionListener{

    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub
            moveIt();   
    }
}//close inner class
class MyDrawPanel extends JPanel{
    public void paintComponent(Graphics g){
        System.out.println("in repaint"); //for debugging
        g.setColor(Color.white);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());

        g.setColor(Color.blue);
        g.fillOval(x, y, 100, 100);
    }
}//close inner class
}
4

2 に答える 2

2

EDT (イベント ディスパッチ スレッド) で長時間実行タスク (スリープ) を実行しています。その結果、EDT がスリープ状態になると、UI を更新できず、再描画が期待どおりに機能しません。

状況を修正するには、常に別のスレッドでスリープします。

このような状況ではSwingWorkerまたはTimerを使用します

スレッドセーフな方法でスイング コンポーネントにアクセスする方法の詳細については、この投稿を参照してください。

更新: このページはそれをよりよく説明しています。

于 2013-01-06T15:20:38.187 に答える
2

ブロックと を呼び出すThread.sleepと、GUI が「フリーズ」します。代わりに、ここでSwing タイマーを使用できます。ActionListenerEDT

于 2013-01-06T15:20:48.523 に答える