image problem
i have to build an gaming application whereby i need to pick image from the file n move them around.
i first made a jframe n then after getting the toolkit and the graphics content i tried to call the drawImage method but it doesn't display the image.
pl can anyone tell me whats te problem or if i'm missing something.
pl do reply
thecode is as below
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class swing1
{
JFrame jf;
Canvas cv;
Container cp;
String me1;
Image img;
Toolkit tk;
Graphics gp;
swing1(String me)
{
me1 = me;
jf = new JFrame(me1);
jf.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we)
{
System.exit(0);
} } );
cv = new Canvas();
jf.setVisible(true);
cp = jf.getContentPane();
cv.setSize(200,300);
cp.add(cv,"Center");
tk = Toolkit.getDefaultToolkit();
img = tk.getImage(getClass().getResource("puyo_blue"));
gp = cv.getGraphics();
gp.drawImage(img,0,0,null);
}
# 1
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class S1
{
S1(String me)
{
JFrame jf = new JFrame(me);
jf.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
});
JPanel panel = new JPanel()
{
Image image = getImage(this);
protected void paintComponent(Graphics g)
{
g.drawImage(image, 10, 10, this);
}
};
Container cp = jf.getContentPane();
cp.add(panel, "Center");
jf.setSize(200,300);
jf.setLocation(200,200);
jf.setVisible(true);
}
private Image getImage(Component c)
{
Toolkit tk = Toolkit.getDefaultToolkit();
Image img = tk.createImage(getClass().getResource("puyo_blue"));
MediaTracker mt = new MediaTracker(c);
mt.addImage(img, 0);
try
{
mt.waitForID(0);
}
catch(InterruptedException e)
{
System.out.println("loading interrupted");
}
if(mt.isErrorAny())
{
System.out.println("loading error: " + mt.statusAll(false));
}
return img;
}
public static void main(String[] args)
{
new S1("hello world");
}
}
# 2
Hello there..
You can't see the image because you're not doing the drawing in the component's update() method. What's happening is that the piece of code that draws to the components (Canvas') graphics context executes, and then is overwritten as soon as its default update() method executes.
You will have to override the update() method (and also paint()) of the Canvas, and do any drawing you wish to do within update().
Suggest you use double buffering to do any animation. It's easier to do the drawing offscreen and simply draw the buffer image when you're done with the drawing. I'm not sure about Swing, but I understand it has an inbuilt buffered canvas or something like that.
A simple code that draws a red box on a black background, using only AWT components is shown below...
import java.awt.*;
import java.awt.event.*;
public class DrawingTest
{
public DrawingTest()
{
Frame myWindow = new Frame("Sample Drawing Test");
myWindow.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
Canvas myCanvas = new MyCanvas();
myWindow.add(myCanvas);
myWindow.pack();
myWindow.setVisible(true);
}
public static void main(String[] args)
{
DrawingTest dt = new DrawingTest();
}
}
// Do all drawing here, in the update method
class MyCanvas extends Canvas
{
Dimension size;
public MyCanvas()
{
size = new Dimension(400, 400);
}
public void paint(Graphics g)
{
update(g);
}
public void update(Graphics g)
{
g.setColor(Color.black);
g.fillRect(0, 0, 400, 400);
g.setColor(Color.red);
g.fillRect(50, 50, 300, 300);
}
public Dimension getPreferredSize()
{
return size;
}
public Dimension getMinimumsize()
{
return size;
}
}
To do animation, you'll also need to use a animation thread, the run() method of whose looks something like this...
Image backBuffer;
// Create this image somewhere (Just a blank image to which you'll do the drawing).
run()
{
Graphics g = backBuffer.getGraphics();
// Do all drawings to Graphics context of backBuffer i.e. g
while(ContinueAnimating)
{
// Delete sprites (animated objects) from old locations
...
// Compute new locations
...
// Check for collisions, etc
...
// Draw sprites at new locations
...
// Done drawing. Now call the update method of the Canvas
myCanvas.repaint();
// Wait for a while to allow AWT to refresh the component.
Thread.sleep(30);
}
}
...
// Update method of MyCanvas
update()
{
// draw the backBuffer Image to canvas' graphics context.
}
Check online tutorials for more details on how to perform animation in Java.
Best regards,
Hamy
# 3
so if i want to make a funtion that draws the image as and when i ask it to i need to call it in the update method and then is when it would draw the image
# 4
one more thing isnt the update function called when we want to redraw the window n i think i'm not redrawing the window then how does the update method gets called
# 5
If you want to drag an image around, you can create a JLabel containing the image and use my Draggable class to make it draggable
you are free to use or modify Draggable, but please do not change the package or take credit for it as your own work
http://forum.java.sun.com/thread.jspa?threadID=690852&messageID=4016833
# 6
Hello,
I've pasted a sample animation proggy below to help you understand this better...
import java.awt.*;
import java.awt.event.*;
// SampleAnimation class
// Overrides update() and paint() methods of Canvas to draw a red box on
// a black background. The position of the box is changed frame by frame
// approx. every 30 ms (30 frames per sec) using a separate thread
// and the canvas is redrawn to show the box in its new position.
public class SampleAnimation
extends Canvas
implements Runnable
{
int i = 100, j = 100;
int idelta = 4, jdelta = 4;
int rectWidth = 50, rectHeight = 50;
int width = 500, height = 400;
Dimension size;
Thread animationThread = null;
public SampleAnimation()
{
super();
size = new Dimension(width, height);
}
// Overridden to draw a red box on a black background.
public void update(Graphics g)
{
g.setColor(Color.black);
g.fillRect(0, 0, width, height);
g.setColor(Color.red);
g.fillRect(i, j, rectWidth, rectHeight);
}
// Overridder to simply call the update() method.
public void paint(Graphics g)
{
update(g);
}
// Return the size of the Canvas
public Dimension getPreferredSize()
{
return size;
}
public Dimension getMinimumSize()
{
return size;
}
// The main animation thread.
public void run()
{
while(animationThread != null)
{
// Move the red box by shifting it's coords by (idelta, jdelta) pixels
if(i >= width - rectWidth || i <= 0)
idelta = 0 - idelta;
if(j >= height - rectHeight || j <= 0)
jdelta = 0 - jdelta;
i += idelta;
j += jdelta;
// Request AWT to redraw the screen
repaint();
// Wait for a few milliseconds (Important to do this to allow
// AWT thread to actually redraw the canvas (i.e. redraw the red box at
// its new position))
try{
Thread.sleep(30);
} catch(InterruptedException e) {}
}
}
// Create the animation thread and start it
public void start()
{
animationThread = new Thread(this, "Sample Animation Thread");
animationThread.start();
}
public static void main(String[] args)
{
Frame mainWindow = new Frame("Sample Animation");
mainWindow.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
});
SampleAnimation sampleAnimation = new SampleAnimation();
mainWindow.add(sampleAnimation);
mainWindow.setResizable(false);
mainWindow.pack();
mainWindow.setVisible(true);
sampleAnimation.start();
}
}
The update method is called on many occasions (like when a component has to be drawn the first time, or when it was hidden behind another window, and now has appeared back on the screen).
But it can also be forced to run using the repaint() method of the component.
What we're doing in the proggy above is very simple..
We've defined a Canvas as our drawing surface, and we do all the drawing in its update() method. So here, we simple draw a black background and a red box at a particular co-ordinate.
To animate this, we've created a thread, and in this thread, we incrementally change the co-ordinate of the box (i, j). (Now why did I use i and j instead of x and y beats me !!!).
Note that by simply changing the coords of the box, we've still not redrawn the box at it's new position. (AND THAT is why you need to call the update() method of the component). This will not happen automatically. To tell AWT to draw the box at its new position, you have to tell it to run the canvas' update() method. You do this by calling the repaint() method of the canvas.
After this, we sleep this thread for some time. This is important to allow the AWT thread to actually repaint the component (Calling repaint() only "requests" AWT to redraw the component at the earliest possible time. And the AWT thread is lower priority to our application thread, so you need to wait in order for AWT to do its job).
Hope this is clear now.
Instead of a box, you could have displayed an image.
This example is the simplest animation you can do. But you'll notice problems like the flickering red box (instead of a smooth one).
To eliminate that, you'll have to use techniques such as double buffering. Please refer to the Java tutorials on Graphics (Probably the old AWT tutorials in the archive section of java tutorials) and even graphics tutorials using Swing.
Best regards,
Hamy
# 7
Here is another sample animation code that uses pure AWT, but this uses Double Buffering. Basically all the drawing is done to a off screen buffer (An image), and when all drawing is done, this buffer is drawn to the canvas at one go (in the overridden update method).
You can copy this code into a file named SampleBufferedAnimation.java and compile and run the same to see how it looks.
If you feel performance is bad, then reduce some of the boxes. Or reduce the size of the screen and backbuffer (but you'll have to change values in a number of place. Sorry for the hardcoding).
import java.awt.*;
import java.awt.event.*;
public class SampleBufferedAnimation
implements Runnable
{
Thread animationThread = null;
BufferedViewport viewport = null;
public SampleBufferedAnimation()
{
Frame mainWindow = new Frame("Buffered Viewport Test");
mainWindow.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
animationThread = null;
System.exit(0);
}
});
viewport = new BufferedViewport(600, 400, 800, 600);
mainWindow.add(viewport);
mainWindow.setResizable(false);
mainWindow.pack();
mainWindow.setVisible(true);
Graphics g = viewport.getGraphics();
animationThread = new Thread(this, "Animation Thread");
animationThread.start();
}
public void run()
{
Graphics g;
int i = 40, j = 40;
int idelta = 5, jdelta = 3;
int x = 100, y = 0;
int xdelta = 1, ydelta = 1;
boolean initialized = false;
long startTime = System.currentTimeMillis();
long executionTime = 0;
AnimatedBox redBox, blueBox, greenBox, whiteBox, yellowBox;
AnimatedBox cyanBox, magentaBox, orangeBox, pinkBox, lightGrayBox;
AnimatedBox redBox1, blueBox1, greenBox1, whiteBox1, yellowBox1;
AnimatedBox redBox2, blueBox2, greenBox2, whiteBox2, yellowBox2;
AnimatedBox redBox3, blueBox3, greenBox3, whiteBox3, yellowBox3;
redBox = new AnimatedBox(Color.red);
blueBox = new AnimatedBox(Color.blue);
greenBox = new AnimatedBox(Color.green);
whiteBox = new AnimatedBox(Color.white);
yellowBox = new AnimatedBox(Color.yellow);
cyanBox = new AnimatedBox(Color.cyan);
magentaBox = new AnimatedBox(Color.magenta);
orangeBox = new AnimatedBox(Color.orange);
pinkBox = new AnimatedBox(Color.pink);
lightGrayBox = new AnimatedBox(Color.lightGray);
redBox1 = new AnimatedBox(Color.red);
blueBox1 = new AnimatedBox(Color.blue);
greenBox1 = new AnimatedBox(Color.green);
whiteBox1 = new AnimatedBox(Color.white);
yellowBox1 = new AnimatedBox(Color.yellow);
redBox2 = new AnimatedBox(Color.red);
blueBox2 = new AnimatedBox(Color.blue);
greenBox2 = new AnimatedBox(Color.green);
whiteBox2 = new AnimatedBox(Color.white);
yellowBox2 = new AnimatedBox(Color.yellow);
redBox3 = new AnimatedBox(Color.red);
blueBox3 = new AnimatedBox(Color.blue);
greenBox3 = new AnimatedBox(Color.green);
whiteBox3 = new AnimatedBox(Color.white);
yellowBox3 = new AnimatedBox(Color.yellow);
while(animationThread != null)
{
startTime = System.currentTimeMillis();
g = viewport.getOffScreenGraphics();
if(g != null)
{
g.setColor(Color.black);
g.fillRect(0, 0, 800, 600);
g.setColor(Color.gray);
for(int fx = 0; fx < 800; fx += 40)
for(int fy = 0; fy < 600; fy += 40)
{
g.fillRect(fx, fy, 20, 20);
g.fillRect(fx + 20, fy + 20, 20, 20);
}
redBox.move(g);
blueBox.move(g);
greenBox.move(g);
yellowBox.move(g);
whiteBox.move(g);
cyanBox.move(g);
magentaBox.move(g);
orangeBox.move(g);
pinkBox.move(g);
lightGrayBox.move(g);
redBox1.move(g);
blueBox1.move(g);
greenBox1.move(g);
yellowBox1.move(g);
whiteBox1.move(g);
redBox2.move(g);
blueBox2.move(g);
greenBox2.move(g);
yellowBox2.move(g);
whiteBox2.move(g);
redBox3.move(g);
blueBox3.move(g);
greenBox3.move(g);
yellowBox3.move(g);
whiteBox3.move(g);
x += xdelta;
y += ydelta;
if(x >= 200 || x <= 0)
xdelta = 0 - xdelta;
if(y >= 200 || y <= 0)
ydelta = 0 - ydelta;
viewport.setViewportPos(x, y);
viewport.repaint();
}
try
{
executionTime = System.currentTimeMillis() - startTime;
Thread.sleep(Math.max(30 - executionTime, 0));
} catch(InterruptedException e) {}
}
}
public static void main(String[] args)
{
SampleBufferedAnimation sampleBufferedAnimation = new SampleBufferedAnimation();
}
}
class AnimatedBox
{
int i, j;
int idelta, jdelta;
Color c;
public AnimatedBox(Color c)
{
this.c = c;
i = 90 + (int) (Math.random() * 350);
j = 90 + (int) (Math.random() * 250);
idelta = 1 + (int) (Math.random() * 10);
jdelta = 1 + (int) (Math.random() * 10);
}
public void move(Graphics g)
{
i += idelta;
j += jdelta;
if(i + 40 >= 800 || i <= 0)
idelta = 0 - idelta;
if(j + 40 >= 600 || j <= 0)
jdelta = 0 - jdelta;
g.setColor(c);
g.fillRect(i, j, 40, 40);
}
}
class BufferedViewport
extends Canvas
{
int width, height;
Dimension size = null;
int bufWidth, bufHeight;
int x, y;
Image offScreenImage = null;
Graphics offScreenGraphics = null;
public BufferedViewport(int width, int height, int bufWidth, int bufHeight)
{
this.width = width;
this.height = height;
this.size = new Dimension(width, height);
this.bufWidth = bufWidth;
this.bufHeight = bufHeight;
}
public Graphics getOffScreenGraphics()
{
return offScreenGraphics;
}
public void setViewportPos(int x, int y)
{
this.x = x;
this.y = y;
}
public void paint(Graphics g)
{
update(g);
}
public void update(Graphics g)
{
if(offScreenImage == null)
{
offScreenImage = createImage(bufWidth, bufHeight);
offScreenGraphics = offScreenImage.getGraphics();
System.out.println("Offscreen buffer created. (" + bufWidth + ", " + bufHeight + ")");
}
g.setClip(0, 0, width, height);
g.drawImage(offScreenImage, -x, -y, null);
}
public Dimension getPreferredSize()
{
return size;
}
public Dimension getMinimumSize()
{
return size;
}
}
# 8
hi thanks all for the help actually this game has been given to me as a means for shortlisting for interview in a company,now what i need to know is that would it b ok if i draw my images simply on the frame without using any canvas etc, or would it not be a good coding practice
# 9
also what does the class Toolkit does as in the below code
private Image getImage(Component c)
{
Toolkit tk = Toolkit.getDefaultToolkit(); // why do we need it
Image img = tk.createImage(getClass().getResource("puyo_blue"));
MediaTracker mt = new MediaTracker(c);
mt.addImage(img, 0);
try
{
mt.waitForID(0);
}
catch(InterruptedException e)
{
System.out.println("loading interrupted");
}
if(mt.isErrorAny())
{
System.out.println("loading error: " + mt.statusAll(false));
}
return img;
}
# 10
> hi thanks all for the help actually this game has
> been given to me as a means for shortlisting for
> interview in a company,
> now what i need to know is that would it b ok if i
> draw my images simply on the frame without using any
> canvas etc, or would it not be a good coding practice
It wouldn't be good coding practice
# 11
If you're writing an applet, then you don't need Toolkit, because the Applet class itself provides methods to create an Image. However, for applications, since you can't use the Applets method (since it's an application and not an Applet), you need a class that provides such a method. And that class for apps is Toolkit.
you can get the system's default Toolkit object, you use the Toolkits static method getDefaultToolkit(). You can then use its getImage or createImage method.
You could load the image also using getImage like below...
tk.getImage("ball.gif");
This will create an Image object from the file "ball.gif"
MediaTracker class provides methods to monitor the status of loading or scaling images. So you can use these methods to check if the image has been fully loaded (and wait till it's fully loaded) and also check if there were any errors while loading the image(s).
And yes, it would be bad practice to draw directly to a Frame. The Canvas component has been specifically made to be overridden for custom graphics, so you should use that.
All the best
- Hamy
# 12
but canvas is an AWT class isnt there anything in swings like a canvas that i can use
i was also thinking to draw a rectangle in the frame and then draw the images on it
would that be ok or for good coding practice i need to use a canvas
also i just came to know about the imageio class cant we draw images with the help of he read method defined in it i think in that case we do not need the toolkit class
also i'm not very clear with a use of a new thread in an application why do we need a thread in gui application what do i do in it
# 13
Hello mate...I guess the best way ahead for you is to check the Java GUI Tutorials. I'm not very well versed with Swing, but I guess the Swing component that can be subclassed for custom animation is JPanel.An trust me, you need threads to perform animation.-