Java Graphics2D AffineTransform Image Rotation - java

I am trying to simply rotate an image in a for loop like so:
class MyCanvas extends JComponent {
AffineTransform identity = new AffineTransform();
Image arrow;
Double angle = -180.0;
public void spin() {
angle += 10.0;
for(int i = 0; i < 10; i++) {
repaint();
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
arrow = Toolkit.getDefaultToolkit().getImage("red-arrow-right-th.png");
// Rotate + translate
AffineTransform trans = new AffineTransform();
trans.setTransform(identity);
trans.translate(getWidth()/2, getHeight()/2);
trans.rotate(Math.toRadians(angle));
System.out.println(trans);
g2.drawImage(arrow, trans, this);
g2.finalize();
}
}
However when I run call spin() in main, it appears to apply only a single rotation, whilst still printing out the loop correctly. What am I overlooking something?

I've transformed your code using the recommendation of MadProgrammer:
Don't override paint, override paintComponent.
Call super.paint before performing any custom painting,
Never call finalize on anything and especially not on objects you didn't create yourself.
Use a Swing Timer
Note the following
A qualified this is used to access the ImageRotationView instance from the ActionListener inner class.
AffineTransform.getRotateInstance returns a transform that rotates coordinates around an anchor point.
Speed can be optimized but it works correctly like this.
This class works as a standalone application
A file named dice.png should be present in the base directory.
.
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
public class ImageRotationFrame {
public static void main(String[] args) {
new ImageRotationFrame();
}
public ImageRotationFrame() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Testing");
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ImageRotationComponent());
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private class ImageRotationComponent extends JComponent {
Image arrow;
double angle = 0.0;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
angle += 0.4;
AffineTransform trans = AffineTransform.getRotateInstance(angle, getWidth() / 2, getHeight() / 2);
((Graphics2D) g).drawImage(arrow, trans, this);
}
public ImageRotationComponent() {
try {
arrow = ImageIO.read(new File("dice.png"));
} catch (IOException e) {
e.printStackTrace();
}
int delay = 500; //milliseconds
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
ImageRotationComponent.this.repaint();
}
};
new Timer(delay, taskPerformer).start();
}
}
}

Related

flickering my jframe even i used doubleBuffer

when I call a repaint method its flickering, I was searching on the internet about doubleBuffered but its stil flickering all of objects on the same time,
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Random;
public class GuiGame extends JFrame implements ActionListener {
private final Flower flower;
private final ArrayList<MyObjects> objekty;
private Image dbImage;
private Graphics dbGraphics;
public GuiGame() {
this.setFocusable(true);
Timer timer = new Timer(40, this);
timer.start();
this.setVisible(true);
/*
public void paint(Graphics g) {
this.dbImage = this.createImage(this.getWidth(), this.getHeight());
this.dbGraphics = this.dbImage.getGraphics();
this.paintComponents(g);
g.drawImage(this.dbImage, 0 ,0, this);
}
*/
public void paint(Graphics g) {
//when i use doubleBuffering this method was called paintComponents
g.drawImage(background.getImage(), 0, 0, this);
g.drawImage(flower.getImage(), flower.getPozX(), flower.getPozY(), this);
String skore = "Score: " + player.getScore() ;
g.drawString(skore, 20, 50);
this.paintObjects(g);
}
public void paintObjects(Graphics g) {
if (this.objekty != null) {
for (objekty o : this.objekty) {
o.move();
g.drawImage(o.getImage(), o.getPozX(), o.getPozY(), this);
}
}
}
when I used doubleBuffering I tried to slow down a timer e.g. to 1000, it was blank page for most of the time and my objects was there only for moment.
when I do not used it, only last objects which i draw were flickering.
how can I avoid?
I would recommend you start by taking a look at Painting in AWT and Swing and Performing Custom Painting.
Swing components, when used correctly, are double buffered by default.
Painting is very complex, there's a lot of work that goes into a paint pass. When you override a "paint" method, you either need to honour the existing workflow (ie, call the super.paintXxx method) or be prepared to take over the full responsibility of the method. Your code has circumvented whole sections of the paint workflow, this is never a good idea.
It's not generally recommend that you extend from top level containers like JFrame, you're not adding any new functionality and they are generally complex components to start with. JFrame for example, is actually a composite component, that is, it has a number of child components added to it that form it's core functionality
By overriding paint (of JFrame), you start competing with these components, and because a child component can be painted without the parent been involved, this can lead to any number of issues.
Instead, start with a JPanel and override it's paintComponent method, this guarantees that you will be operating in a double buffered workflow.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class MainPane extends JPanel {
private int xDelta = 1;
private int xPos = 0;
private BufferedImage ufo;
public MainPane() throws IOException {
ufo = ImageIO.read(getClass().getResource("/images/ufo.png"));
Timer timer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += xDelta;
if (xPos + ufo.getWidth() > getWidth()) {
xPos = getWidth() - ufo.getWidth();
xDelta *= -1;
} else if (xPos < 0) {
xPos = 0;
xDelta *= -1;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
paintUFO(g2d);
g2d.dispose();
}
protected void paintUFO(Graphics2D g2d) {
int y = (getHeight() - ufo.getHeight()) / 2;
g2d.drawImage(ufo, xPos, y, this);
}
}
}

Trouble with for loop

I have a for loop that iterates within an actionPerformed method. Basically, I have a car game. I have a panel where car images travel from side to side in a JPanel. I am trying to have the cars stop at the finish line (I am doing that by sleeping when the image reaches a certain x value) display the race results, leave the screen and race again. I need to do that four times until we have a winner.
private class RaceDisplay extends JPanel implements ActionListener{
private Image img1,img2;
private int velX1,velX2;
private int x1,x2;
private Timer tm;
private JTextArea text1 = new JTextArea();
public RaceDisplay(){
tm = new Timer(30,this);
x1=0;
x2=0;
velX1=2;
velX2 =2;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
ImageIcon car1 = new ImageIcon("...");
ImageIcon car2 = new ImageIcon("...");
img1 = car1.getImage();
img2 = car2.getImage();
g.drawImage(img1,x1,100,null);
g.drawImage(img2,x2,200,null);
tm.start();
}
public void actionPerformed(ActionEvent e) {
x1=x1+velX1;
velX2= x2+velX2;
repaint();
for(int count = 0;count<=4;count++){//<-----loop with issues.
if(count == 1){
text1.setText(result());
}
if(x1>=650 && x2>=650){ //does this when both cars reach the line
velX1=0;
velX2=0;
try {
Thread.sleep(2500);
} catch (InterruptedException ex) {
Logger.getLogger(Display.class.getName()).log(Level.SEVERE, null, ex);
}
x1=0;
x2=0;
repaint();
velX1= x1+velX1;
velX2= x2+velX2;
}
}
repaint();
}
I created the for loop that should check the if statements when it reaches the last counter it displays the winner(method for winner in the code). I was expecting the images to travel from side to four times and display the results four times.
But it only display anything if i set the if(counter==1) to (counter==0).
Can anyone help?
Thanks.
Don't call tm.start(); from within the paintComponent method, this is just asking for trouble. Painting may occur for any number of reasons, many of which you don't control or have knowledge about
Don't call Thread.sleep from within the context of the Event Dispatching Thread. This isn't stopping the Timer, but is prevent the EDT from processing the Event Queue, which includes things like repaint events and timer events...
Instead, once you've detected that a car has passed the finish line, you can either, stop updating that car's position and/or stop the Timer
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Map<BufferedImage, Rectangle> carBounds;
private BufferedImage blueCar;
private BufferedImage redCar;
public TestPane() {
carBounds = new HashMap<>(25);
try {
blueCar = ImageIO.read(getClass().getResource("/BlueCar.png"));
redCar = ImageIO.read(getClass().getResource("/RedCar.png"));
int x = 0;
int y = (200 / 2 ) - blueCar.getHeight();
carBounds.put(blueCar, new Rectangle(x, y, blueCar.getWidth(), blueCar.getHeight()));
y = (200 / 2);
carBounds.put(redCar, new Rectangle(x, y, redCar.getWidth(), redCar.getHeight()));
} catch (IOException ex) {
ex.printStackTrace();
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (BufferedImage img : carBounds.keySet()) {
Rectangle bounds = carBounds.get(img);
int xDelta = (int)Math.round((Math.random() * 7) + 1);
bounds.x += xDelta;
if (bounds.x + bounds.width > getWidth()) {
bounds.x = getWidth() - bounds.width;
((Timer)e.getSource()).stop();
}
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (BufferedImage img : carBounds.keySet()) {
Rectangle bounds = carBounds.get(img);
g2d.drawImage(img, bounds.x, bounds.y, this);
}
g2d.dispose();
}
}
}
Take a closer look at Concurrency in Swing for more details

gif animation flickering in applet

My gif animation flickers too much. I've heard about double buffering that can help but how do I do that to my gif animation? Or is there a better faster shortcut to it. This is just a small test applet thing Im doing for fun but will implement the lessons in class.
Context:
import java.net.*;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class HiroshimaBlock extends Applet implements ActionListener {
TextField distanceText = new TextField(10);
TextField accelerationText = new TextField(10);
Button security = new Button("Account Manager");
Button launch = new Button("LAUNCH!");
Button Reportl = new Button("Report Logs");
Image dancer;
URL base;
MediaTracker mt;
Timer tm = new Timer(10, this);
TextArea answers = new TextArea("I am ready for your first trip.", 4, 20,
TextArea.SCROLLBARS_NONE);
Image image;
#Override
public void init() {
setSize(550, 500);
// Some messages for the top of the Applet:
addHorizontalLine(Color.orange);
addNewLine();
// JOptionPane.showMessageDialog(null, "HiroshimaBlock",
// "Welcome to HiroshimaBlock", JOptionPane.PLAIN_MESSAGE);
// The two text fields and the launch button:
Frame c = (Frame) this.getParent().getParent();
c.setTitle("HiroshimaBlock");
mt = new MediaTracker(this);
try {
base = getDocumentBase();
} catch (Exception e) {
}
dancer = getImage(base, "dancer1.gif");
mt.addImage(dancer, 9);
try {
mt.waitForAll();
} catch (InterruptedException e) {
}
loadImage();
// add(distanceText);
// add(new Label("Distance of trip in light years"));
addNewLine();
addNewLine();
// add(accelerationText);
// add(new Label("Acceleration of rocket in g's"));
addNewLine();
add(launch);
addNewLine();
add(security);
addNewLine();
add(Reportl);
// A text area for printing the answers:
// answers.setEditable(false);
// add(answers);
addNewLine();
addNewLine();
addHorizontalLine(Color.orange);
}
public void loadImage() {
URL url = getClass().getResource("hsblock.png");
image = getToolkit().getImage(url);
}
public void paint(Graphics g) {
g.drawImage(image, 20, 20, this);
this.security.setLocation(25, 200);
addNewLine();
this.launch.setLocation(25, 230);
this.Reportl.setLocation(25, 260);
this.security.setSize(100, 25);
this.launch.setSize(100, 25);
this.Reportl.setSize(100, 25);
g.drawImage(dancer, 150, 200, this);
tm.start();
}
private void addHorizontalLine(Color c) {
// Add a Canvas 10000 pixels wide but only 1 pixel high, which acts as
// a horizontal line to separate one group of components from the next.
Canvas line = new Canvas();
line.setSize(10000, 1);
line.setBackground(c);
add(line);
}
private void addNewLine() {
// Add a horizontal line in the background color. The line itself is
// invisible, but it serves to force the next Component onto a new line.
addHorizontalLine(getBackground());
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
You want to:
Create a drawing class that extends JPanel (or JComponent)
Override the paintComponent(Graphics g) method of your class.
Call the super's method first in this method
And then do your animation drawing in this method.
This will give you Swing's automatic double buffering which should help smooth out your animation.
Display your drawing JPanel in your JApplet by adding it to the applet's contentPane.
For example:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.nio.Buffer;
import javax.swing.*;
public class SimpleAnimation extends JApplet {
#Override
public void init() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
DrawPanel drawPanel = new DrawPanel();
getContentPane().add(drawPanel);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
}
class DrawPanel extends JPanel {
private static final int I_WIDTH = 20;
private static final int I_HEIGHT = 20;
private static final int TIMER_DELAY = 15;
private int x = 0;
private int y = 0;
private BufferedImage img = new BufferedImage(I_WIDTH, I_HEIGHT, BufferedImage.TYPE_INT_ARGB);
public DrawPanel() {
Graphics2D g2 = img.createGraphics();
g2.setColor(Color.red);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.fillOval(1, 1, I_WIDTH - 2, I_HEIGHT - 2);
g2.dispose();
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, x, y, this);
}
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
x++;
y++;
repaint();
}
}
}
Well LOL I made it stop flickering by using update LOLOLOL
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Test extends Applet {
Image img;
public void init() {
setSize(700, 700);
img = getImage(getDocumentBase(), "dancer1.gif");
}
public void update(Graphics g) {
g.drawImage(img, 140, 200, this);
}
public void paint(Graphics g) {
update(g);
}
}

Java applet repaint a moving circle

I've just moved over from Pygame so Java 2D in an applet is a little new to me, especially when it comes to repainting the screen. In pygame you can simply do display.fill([1,1,1]) but how do I do this in an applet in Java? I understand the use of repaint() but that doesn't clear the screen - any moving object is not 'removed' from the screen so you just get a long line of painted circles.
Here's my code that I've been testing with:
package circles;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
public class circles extends Applet implements Runnable {
private static final long serialVersionUID = -6945236773451552299L;
static Random r = new Random();
String msg = "Click to play!";
static int w = 800, h = 800;
int[] txtPos = { (w/2)-50,(h/2)-50 };
int[] radiusRange = { 5,25 };
int[] circles;
static int[] posRange;
int x = 0, y = 0;
int radius = 0;
int cursorRadius = 10;
boolean game = false;
public static int[] pos() {
int side = r.nextInt(5-1)+1;
switch(side) {
case 1:
posRange = new int[]{ 1,r.nextInt(w),r.nextInt((h+40)-h)+h,r.nextInt(270-90)+90 };
break;
case 2:
posRange = new int[]{ 2,r.nextInt((w+40)-w)+w,r.nextInt(h),r.nextInt(270-90)+90 };
break;
case 3:
posRange = new int[]{ 3,r.nextInt(w),r.nextInt(40)-40,r.nextInt(180) };
break;
case 4:
posRange = new int[]{ 4,r.nextInt(40)-40,r.nextInt(h),r.nextInt(180) };
break;
}
System.out.println(side);
return posRange;
}
public void start() {
setSize(500,500);
setBackground(Color.BLACK);
new Thread(this).start();
}
public void run() {
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics e) {
Graphics2D g = (Graphics2D) e;
if(System.currentTimeMillis()%113==0) {
x+=1;
y+=1;
}
g.setColor(Color.BLUE);
g.fillOval(x,y,20,20);
repaint();
}
}
You need to call super.paint(g); in your paint method, as to not leave paint artifacts.
Never call repaint() from inside the paint method
Don't explicitly call paint, as you do in update(), when you mean to call reapaint()
just update the x and y values from inside the update() method, then call repaint()
You don't need to take a Graphics argument in update()
You need to call update() somewhere repeatedly in a loop, as it updates the x and y and reapint()s
If your class is going to be a Runnable, then you should put some code in the run() method. That's probably where you should have your loop
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class circles extends Applet implements Runnable {
int x = 0, y = 0;
public void start() {
setSize(500, 500);
setBackground(Color.BLACK);
new Thread(this).start();
}
public void run() {
while (true) {
try {
update();
Thread.sleep(50);
} catch (InterruptedException ex) {
}
}
}
public void update() {
x += 5;
y += 6;
repaint();
}
public void paint(Graphics e) {
super.paint(e);
Graphics2D g = (Graphics2D) e;
g.setColor(Color.BLUE);
g.fillOval(x, y, 20, 20);
}
}
Side Notes
Why use Applets in the first place. If you must, why use AWT Applet and not Swing JApplet? Time for an upgrade.
Here's how I'd redo the whole thing in Swing, using a Swing Timer instead of a loop and Thread.sleep, as you should be doing.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Circle extends JPanel{
private static final int D_W = 500;
private static final int D_H = 500;
int x = 0;
int y = 0;
public Circle() {
setBackground(Color.BLACK);
Timer timer = new Timer(50, new ActionListener(){
public void actionPerformed(ActionEvent e) {
x += 5;
y += 5;
repaint();
}
});
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval(x, y, 20, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_W, D_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new Circle());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
See How to use Swing Timers
See Create GUIs with Swing
Here's more advanced example for you to look at and ponder.
UPDATE
"Problem is, that's a JPANEL application. I specifically want to make an applet easily usable on a web page. "
You can still use it. Just use the JPanel. Take out the main method, and instead of Applet, use a JApplet and just add the JPanel to your applet. Easy as that.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CircleApplet extends JApplet {
#Override
public void init() {
add(new Circle());
}
public class Circle extends JPanel {
private static final int D_W = 500;
private static final int D_H = 500;
int x = 0;
int y = 0;
public Circle() {
setBackground(Color.BLACK);
Timer timer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
x += 5;
y += 5;
repaint();
}
});
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval(x, y, 20, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_W, D_H);
}
}
}

Image animation not getting displayed

I have the following code.I want to display the images in my chick array on the screen after some time delay.The coordinates have to be shifted by 10px each x direction when the new
image is loaded.I would like to know what additional code snippets can i add in this code to have an animation on my Frame with the two images i have .Below is my code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
public class Chicken extends Frame implements Runnable{
Thread animation;
long frameDelay = 3000;
Image chick[] = new Image[2];
int numFrames = chick.length;
Toolkit tk = getToolkit();
public Chicken()
{
setSize(new Dimension(300,300));
setVisible(true);
setBackground(Color.BLACK);
animation = new Thread(this);
chick[0] = tk.createImage("stand.png");
chick[1] = tk.createImage("walk.png");
animation.start();
//setVisible(false);
}
public void paint(Graphics g)
{
g.drawImage(chick[0],100,100,null );
}
#Override
public void run() {
// TODO Auto-generated method stub
repaint();
try {
Thread.sleep(frameDelay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String args[])
{
Chicken instance = new Chicken();
}
}
So, the first problem you have is a resource issue.
Resources stored "within" the application (typically known as embedded resources) can't be loaded like external resources.
chick[0] = tk.createImage("stand.png");
Is expecting a file "./stand.png" which doesn't exist. Instead, you need to load the resource through the Class#getResource API...
chick[0] = tk.createImage(getClass().getResource("/stand.png"));
The second problem you will face is the fact that you are overriding paint of a top level container. This really shouldn't be done. Let's start with the fact it's not double buffered and end with the fact that frames have decorations which sit inside the viewable area. This means that the decorations will overlap what ever you paint to the surface...not pretty...
The third problem is you are not telling the image where it should move to. It's static.
You need some kind of x/y value that tells the image where it should be painted. You would modify these values by a given x/y delta within you thread before you called repaint...
The forth problem you might have is the fact that you are using AWT...which is kind of dated. Swing would solve your double buffering issue for you...IMHO, would make a better choice - there's a lot more documentation and examples on Swing laying around now days ;)
While I'm on my hobble horse...I would, personally, recommend ImageIO over Toolkit#createImage or ImageIcon, mostly because it supports more formats, but also because it will throw an Exception when the image can't be read for some reason...
I have a simple example if Swing, but I won't post it, because I'll get in trouble for running of topic...let me know if you would like to see it
Updated with Swing example
This uses a embedded image in the default package...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ChickenDance {
public static void main(String[] args) {
new ChickenDance();
}
public ChickenDance() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage chicken;
private int xPos;
private int yPos;
private int xDelta = 4;
public TestPane() {
try {
chicken = ImageIO.read(getClass().getResource("/Chicken.png"));
} catch (IOException ex) {
Logger.getLogger(ChickenDance.class.getName()).log(Level.SEVERE, null, ex);
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += xDelta;
if (xPos + chicken.getWidth() > getWidth()) {
xPos = getWidth() - chicken.getWidth();
xDelta *= -1;
} else if (xPos < 0) {
xPos = 0;
xDelta *= -1;
}
yPos = (getHeight() - chicken.getHeight()) / 2;
repaint();
}
});
if (chicken != null) {
timer.start();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (chicken != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(chicken, xPos, yPos, this);
g2d.dispose();
}
}
}
}

Categories

Resources