viniolli
viniolli

Reputation: 219

Java - repaint JPanel 2 times in one method

This is simple version of my problem. I have 3 classes: public class TopographyFrame extends JFrame - simple JFrame with JPAnel and button public class TopograpyPanel extends JPanel - JPanel to fill Rectangles public class Siec - class to perform calculations and call repaint on JPAnale

in JPanel i overided paintComponent() method

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 - array of objects with field public Color winner

in class Siec i have reference to JPanel to repaint it in class JFrame i have a button with private action listener:

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();
            }
        }

method forPaint() in Siec looks like:

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 is array of Colors

So my problem is: when i click a button i would like to JPanel repaint immediately and then after 3 second repaint one more time. Insted JPanel repaints only one time after 3s delay. }

Upvotes: 0

Views: 1589

Answers (3)

Nate
Nate

Reputation: 557

Since your sleep is being performed on the Event Dispatch Thread, the repaint() event cannot be performed until the end of the wait. Do this instead:

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();
        }
    });
}

Keep in mind that all modifications to a Swing component (e.g. your JPanel) must happen on the EDT.

Upvotes: 0

Mattias Isegran Bergander
Mattias Isegran Bergander

Reputation: 11909

You are scheduling a repaint on the UI thread and then sleeping (blocking) the UI thread for 3seconds and then requesting another repaint again. Those two will either happen really close to each other after this method has finished (after 3 seconds) or be merged into one update (afterwards as well). Instead of sleep(3000) and then calling your setTopography again you could schedule a setTopography call on the UI thread to happen after 3 seconds.

Have a look at the Swing Timer for example: http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html

So something along the lines of:

javax.swing.Timer timer = new javax.swing.Timer(3000, new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        setTopography();
    }
});
timer.setRepeats(false);
timer.start();

Upvotes: 1

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81724

You can't sleep, wait, or otherwise pause on the event handling thread, ever. Doing so blocks all events from being processed, including painting events. Your first painting can't occur because you're sleeping on the event thread, preventing it from happening.

The right way to do any kind of animation -- even simple stuff like this -- is to create your own thread. That second thread can call repaint(), sleep for 3 seconds, then call repaint() again. The SwingWorker class is nominally a simpler way to do this, but in all honesty, beginners always find creating their own thread to be easier.

Upvotes: 2

Related Questions