[java] How do you repaint graphics in applet?

Started by
10 comments, last by Glass_Knife 16 years, 8 months ago
import java.awt.*;
import java.applet.*;

public class Test extends Applet implements Runnable {
	int nr = 0;
	Thread thread;
	Dimension d;
    public void init() {
		d = size();
    }
 
    public void run() {
	    long starttime;
	    Graphics g;
	    g=getGraphics();
	    Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
		
	    while(true) {
	      starttime=System.currentTimeMillis();
	      try {
	        paint(g);
	        starttime += 30;
			nr++;
	        Thread.sleep(Math.max(0, starttime-System.currentTimeMillis()));
	      }
	      catch (InterruptedException e) {
	        break;
	      }
	    }
    }
    public void start() {
	    if (thread == null) {
	      thread = new Thread(this);
	      thread.start();
	    }
	  }

    public void stop() {
	    if (thread != null) {
	      thread.stop();
	      thread = null;
	    }
	}
    public void paint(Graphics g)
    {
		g.setColor(Color.WHITE);
		g.fillRect(0,0,d.width,d.height);
		g.setColor(Color.MAGENTA);
                g.drawString(nr, 10, 10);
    }
}

My applet is blinking. How do I make it to do not blink? [Edited by - Himent on August 3, 2007 12:07:15 PM]
Advertisement
You need to setup a backbuffer as a BufferedImage which is the same size as the applet and draw to that first. Then on a TIMED interval draw to the applet.

You can setup the back buffer with the following couple of lines of code

//add this as a class variable
private BufferedImage bkbuffer = null;

Then in the init() method you want to create the BufferedImage after getting the size.

bkbuffer = new BufferedImage( d.getWidth(), d.getHeight(), BufferedImage.TYPE_INT_ARGB );

Then in your run() method change

g=getGraphics();

to

g = bkbuffer.getGraphics();

Then after the paint(g) line add the following

getGraphics().drawImage(bkbuffer,0,0,null);

That should reduce flickering if not eliminate flickering.

One additional thing and that is you do not want to be changing the priority of the thread. You might have done this to try and reduce the flickering so I advise removing it. You do not need to be sleeping but instead look into using TimerTask it is much more efficient and intuitive.
Alternatively, you could extend JApplet instead of Applet which iirc automatically provides double buffering.
-LuctusIn the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move - Douglas Adams
Yes, use JApplet.

Second, use the kosher way of implementing custom drawing:
public void paintComponent(Graphics g){  super.paintComponent(g); // optional}


Next, update only in Swing's event loop, by calling repaint on your applet.

So in the end, you have something like this:
public class Test extends JApplet{  public void run()  {    try {      long time = System.currentTimeMillis();      while (running) {        long curr = System.currentTimeMillis();        long delta = curr-time;        time = curr;        // update the logic        ...        doLogicStuff( delta );        repaint();        Thread.sleep( 1 );      }    } catch (Exception e) {      e.printStackTrace();    }  }  public void paintComponent(Graphics g){     // draw the stuff  }  }


Also - never mess with thread priority.
import java.awt.*;import javax.swing.*;public class Test extends JApplet implements Runnable {	int nr = 0;    public void run() {		while (true) {		    try {				nr++;				repaint();				Thread.sleep(20);		    } catch (Exception e) {				e.printStackTrace();		    }		}    }    public void paint(Graphics g){		g.setColor(Color.MAGENTA);        g.drawString("-"+nr, 10, 10);    }}

Why it's not working?
Try paintComponent, not paint.
Quote:Original post by Antheus
Try paintComponent, not paint.


It doesn't call run() method...
Here is an implementation that I have observed absolutely no flickering with.

import java.awt.Color;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.util.Timer;import java.util.TimerTask;import javax.swing.JApplet;public class Test extends JApplet {	private int nr = 0;	private BufferedImage bkbuffer = null;	private Timer tasker = new Timer();	public void init() {		this.setIgnoreRepaint(true);		bkbuffer = new BufferedImage(getWidth(), getHeight(),				BufferedImage.TYPE_INT_ARGB);		TimerTask t = new TimerTask() {			public void run() {				Graphics g;				//g=getGraphics();				g = bkbuffer.getGraphics();				paint(g);				nr++;				getGraphics().drawImage(bkbuffer, 0, 0, null);			}		};		//render every 16 milliseconds		tasker.schedule(t, 100, 16);	}	public void paint(Graphics g) {		g.setColor(Color.WHITE);		g.fillRect(0, 0, getWidth(), getHeight());		g.setColor(Color.MAGENTA);		g.drawString(" " + nr, 40, 40);	}}

Try this and let me know if flickering occurs at all.
Quote:Original post by 5MinuteGaming
Here is an implementation that I have observed absolutely no flickering with.

*** Source Snippet Removed ***
Try this and let me know if flickering occurs at all.


Thanks, it's not flickering!
Good to hear Himent! Glad I could help, just post if you have anymore problems.

This topic is closed to new replies.

Advertisement