0

これは私の問題の単純なバージョンです。私は3つのクラスを持っています: public class TopographyFrame extends JFrame - JPAnel とボタンを備えたシンプルな JFrame public class TopograpyPanel extends JPanel - JPanel to fill Rectangles public class Siec - 計算を実行し、JPAnale で repaint を呼び出すクラス

JPanel で、paintComponent() メソッドをオーバーライドしました

public void paintComponent (Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        System.out.println(rectangles.length);
        for(int i = 0 ; i < rectangles.length ; i++){
            g2.setPaint(neurony[i].winner);
            g2.fillRect((int)rectangles[i].x,(int)rectangles[i].y,(int)rectangles[i].width, (int)rectangles[i].height);
        }
    }

neurony - フィールド public Color を持つオブジェクトの配列

クラスSiecでは、クラスJFrameで再描画するためにJPanelへの参照があります。プライベートアクションリスナーを持つボタンがあります。

class MyListener implements ActionListener{
        Siec s;
        public MyListener(Siec s){
            this.s = s;
        }
        public void actionPerformed(ActionEvent arg0) {
            try {
                s.forPaint();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

Siec の forPaint() メソッドは次のようになります。

public void forPaint(){

        setTopography();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        setTopography();
    }
public void setTopography() {
    for (int i = 0; i < vector.colors.length; i++) {
            neurony[i].winner = vector.colors[(int)(random() * 900 % vector.colors.length)];
    }
    panel.repaint();
}

vector.color は色の配列です

だから私の問題は、ボタンをクリックするとすぐにJPanelを再描画し、3秒後にもう一度再描画したいということです。Insted JPanel は、3 秒の遅延後に 1 回だけ再描画します。}

4

3 に答える 3

2

イベント処理スレッドでスリープ、待機、または一時停止することはできませ。これを行うと、ペイント イベントを含むすべてのイベントが処理されなくなります。イベント スレッドでスリープしているため、最初の描画は実行できず、実行できません。

あらゆる種類のアニメーションを行う正しい方法は (このような単純なものであっても)、独自のスレッドを作成することです。その 2 番目のスレッドは、repaint() を呼び出し、3 秒間スリープしてから、repaint() を再度呼び出すことができます。SwingWorkerクラスは名目上、これを行うためのより簡単な方法ですが、正直なところ、初心者は常に独自のスレッドを作成する方が簡単であることに気付きます。

于 2012-04-30T20:31:07.430 に答える
1

UI スレッドで再描画をスケジュールし、UI スレッドを 3 秒間スリープ (ブロック) してから、別の再描画を再度要求しています。これら 2 つは、このメソッドが終了した後(3 秒後)に非常に接近して発生するか、(その後も) 1 つの更新にマージされます。sleep(3000)もう一度呼び出す代わりに、UI スレッドで呼び出しを 3 秒後にsetTopographyスケジュールすることができます。setTopography

たとえば、Swing Timer を見てください: http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html

したがって、次のようなものがあります。

javax.swing.Timer timer = new javax.swing.Timer(3000, new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        setTopography();
    }
});
timer.setRepeats(false);
timer.start();
于 2012-04-30T20:38:20.810 に答える
0

スリープはEvent Dispatch Threadで実行されているため、 repaint() イベントは待機が終了するまで実行できません。代わりにこれを行います:

private Timer timer = new Timer(); // use java.util.Timer

public void forPaint() {

    setTopography();

    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            setTopography();
        }

    }, 3000);

}

public void setTopography() {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {

            for (int i = 0; i < vector.colors.length; i++) {
                neurony[i].winner = vector.colors[(int)(random() * 900 % vector.colors.length)];
            }
            panel.repaint();
        }
    });
}

Swing コンポーネント (JPanel など) に対するすべての変更は EDT で行う必要があることに注意してください。

于 2012-04-30T20:43:40.213 に答える