0

I have tried Tread.sleep but it delays the whole program and not just the loop. I want to draw a line in an SFrame, but I want it to draw the line slowly.

 public class Panel extends javax.swing.JPanel  
{  
    int a=0;
    int b=0;
    public void paint(java.awt.Graphics g) 
    {     
        g.setColor(Color.GREEN);  
        g.fillRect(0,0,500,500); 
        g.setColor(Color.BLACK);  

        while( a<=500&&b<=500){
            g.fillRect(a,b,5,5);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {}               
            a++;
            b++;

        }

    } 
Leo
  • 11
  • 3
    do it in a seperate thread. then you can let that thread "sleep", while the rest continues. for instance a deamon thread. that's a thread that runs in the background, without blocking the flow of your application – Stultuske Jan 30 '19 at 13:03
  • You shouldn't put a sleep in the thread that's painting your component, because your application relies on that thread to be running. You need to separate your state update and timing from your rendering. Adjust a variable on a timer in another thread, and repaint the panel each time with the new state. – khelwood Jan 30 '19 at 13:05
  • You could paint your line incrementally, but khelwood has the better idea – DarceVader Jan 30 '19 at 13:06
  • Possible duplicate of [Java Swing Applet: How to slow or delay paint() without slowing down the entire program](https://stackoverflow.com/questions/6405833/java-swing-applet-how-to-slow-or-delay-paint-without-slowing-down-the-entire) – Nico Haase Jan 30 '19 at 13:08
  • Use a swing `Timer` and in its periodic callback method do `a++; b++; Panel.this.repaint();` – Joop Eggen Jan 30 '19 at 13:26

1 Answers1

4

You misinterpret the way Graphics works. You cannot simply 'delay' the rendering by drawing something later. That would either delay your rendering thread, or not be rendered on the screen at all.

The reason for this is that the drawing of all your repainted components needs to be complete, before the rendering is done. However, if you incrementally draw the line, the entire process will wait until the loop is terminated for the program to continue (and the line to be shown). Think of the draw method as the shutter of a camera. You make a quick picture, not a video. So for something to 'move' or draw slowly, you need to put a lot of pictures in sequence, like in a movie.

What you actually want is to redraw your Panel periodically (you need a frame-rate). So for instance, if you wanted to render with something close to 30 frames a second, you could do:

public class AutoUpdatedPanel extends javax.swing.JPanel {
    Thread t;
    float linePercent = 0f;

    public AutoUpdatedPanel () {
        t = new AutoUpdateThread();
        t.start();
    }

    public void paint(java.awt.Graphics g) {     
        g.setColor(Color.GREEN);  
        g.fillRect(0, 0, 500, 500); 
        g.setColor(Color.BLACK);  

        int linePos = (int) 5 * linePercent;
        g.fillRect(linePos, linePos, 5, 5);
    }

    public class AutoUpdateThread extends java.lang.Thread {
        public void run() {
            while (!isInterrupted()) {
                try {
                    Thread.sleep(33);
                } catch (InterruptedException e) {
                    // silent.
                }
                linePercent += .5f;
                linePercent = math.min(linePercent, 100f);
                AutoUpdatedPanel.this.repaint();
            }
        }
    }
}

However I would advice to make the growth of the line time-based:

    ...

    public class AutoUpdateThread extends java.lang.Thread {
        public void run() {
            while (!isInterrupted()) {
                try {
                    Thread.sleep(33);
                } catch (InterruptedException e) {
                    // silent.
                }

                nowMillis = Calendar.newInstance().getTimeInMillis();
                long timeOffset = nowMillis - start;
                linePercent = (float) (.002d * timeOffset);
                linePercent = math.min(linePercent, 100f);
                AutoUpdatedPanel.this.repaint();
            }
        }
    }
TreffnonX
  • 2,924
  • 15
  • 23