You are suffering from several problems, DemonPants has pointed out your call to repaint() in the paint method is bad - it will cause the EDT (EventDispatchThread) to be flooded with repaint events continually redrawing your Applet. While this behaviour isn't inherently bad (it is essentially a primitive form of game loop), it probably isn't what you are intending.
As to the reason why your 1st sample appears to work, and your 2nd does not - that is a little more complicated.
Lets start with this :-
this.getImage(new URL(this.getCodeBase(), "dude.png"))
Component.getImage(...) (which falls through to Toolkit.getImage(...) does return an Image object - however it is returned
unloaded. This means it is not ready to be drawn to the screen.
The data for the Image only begins to be loaded the first time you try and use the Image (in your case, this is the first time you attempt to draw it). This loading process however occurs asynchronously, and until it is complete any attempt to draw the image will result in nothing happening.
This is the cause of your 2nd code example not working - your init() method is invoked only once, therefore your first attempt to copy the "dude.png" onto your "i Image" results in failure because the image has yet to be loaded.
As to the reason your 1st code example DOES work - this is yet more complex!
If we go back to:-
this.getImage(new URL(this.getCodeBase(), "dude.png"))
if you take a look at the javadoc for Toolkit.getImage(...) you will see the documentation mentions that it attempts to cache requests for the same image:
The underlying toolkit attempts to resolve multiple requests with the same filename to the same returned Image.
This cache is unwittingly the reason why your first code example works. As your first example repeatedly attempts to load the same image each repaint cycle, the Toolkits underlying cache will be returning you the same Image object. Eventually the Image's loading will complete and the subsequent copy onto the "i Image" will be successful.
I'll annotate your code to better explain the exact sequence of steps, so you can better see this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class AppTest extends Applet { Image i; public void init() { } public void paint(Graphics g) { i = createImage(this.getWidth(), this.getHeight()); Graphics b = i.getGraphics(); try { Image img = this.getImage(new URL(this.getCodeBase(), "dude.png")); b.drawImage(img, 0, 0, null); } catch (MalformedURLException e) { e.printStackTrace(); } b.dispose(); g.drawImage(i, 0, 0, null); repaint(); } } |
Here is a modified version of your code, i've left the repaint() call at the end of the paint method, so you can see it allows for a primitive way of animating.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| import java.applet.Applet; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Image; import java.awt.MediaTracker; import java.net.MalformedURLException; import java.net.URL;
public class DudeApplet extends Applet { Image dude; public void init() { try { dude = getImage(new URL(this.getCodeBase(), "dude.png")); MediaTracker imageLoader = new MediaTracker(this); imageLoader.addImage(dude, 0); imageLoader.waitForAll(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }
g.setColor(Color.BLACK); g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(dude, (int)((getWidth()-dude.getWidth(null)) *Math.random()), (int)((getWidth()-dude.getWidth(null)) *Math.random()), null); repaint(); } } |