Reputation: 701
I'm trying to get an image to paint on the screen using java's Graphics2D. Here is the code I'm using. I want to see an image move steadily across the screen. At the moment I can see the image but it does not move unless I resize the window, in which case it DOES move. I have sketched out the classes below.
public class Tester extends JFrame {
private static final long serialVersionUID = -3179467003801103750L;
private Component myComponent;
public static final int ONE_SECOND = 1000;
public static final int FRAMES_PER_SECOND = 20;
private Timer myTimer;
public Tester (Component component, String title) {
super(title);
myComponent = component;
}
public void start () {
myTimer = new Timer(ONE_SECOND / FRAMES_PER_SECOND, new ActionListener() {
@Override
public void actionPerformed (ActionEvent e) {
repaint();
}
});
myTimer.start();
}
@Override
public void paint (Graphics pen) {
if (myComponent != null) {
myComponent.paint(pen);
}
}
}
The Component object passed to Tester is the following class:
public class LevelBoard extends Canvas implements ISavable {
private static final long serialVersionUID = -3528519211577278934L;
@Override
public void paint (Graphics pen) {
for (Sprite s : mySprites) {
s.paint((Graphics2D) pen);
}
}
protected void add (Sprite sprite) {
mySprites.add(sprite);
}
I have ensured that this class has only one sprite that I have added. The sprite class is roughly as follows:
public class Sprite {
private Image myImage;
private int myX, myY;
public Sprite () {
URL path = getClass().getResource("/images/Bowser.png");
ImageIcon img = new ImageIcon(path);
myImage = img.getImage();
}
public void update () {
myX += 5;
myY += 5;
}
public void paint (Graphics2D pen) {
update();
pen.drawImage(myImage, myX, myY,null);
}
However, I see only a stationary image of bowser on the screen. He does not move unless the window is resized. I know that the paint(Graphics2D pen) method in the Sprite class is being called at particular intervals (because of the Timer in the Tester class). However, even though the x and y positions are being incremented by 5 each time. The sprite does not move. Why not? How do I fix it? I'm just trying to test some other features of my program at the moment so I really just need to get this up and running. I don't really care how.
Upvotes: 1
Views: 1773
Reputation: 47608
Your code is full of problems:
JFrame.paint()
, especially if not calling super
. Set a ContentPane and override its paintComponent()
. While it may seem convenient, it is usually a bad design and unnecessary.JComponent.paint()
, but rather override JComponent.paintComponent()
(and call super
)JLabel
to display an image. It's much simpler.Here is a simple example showing a Bowser moving around the frame. (It's funny when you reduce the frame size and hit the image with the frame border ;-))
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UnsupportedLookAndFeelException;
public class TestAnimation2 {
private static final int NB_OF_IMAGES_PER_SECOND = 50;
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
private Random random = new Random();
private double dx;
private double dy;
private double x = WIDTH / 2;
private double y = HEIGHT / 2;
protected void initUI() throws MalformedURLException {
final JFrame frame = new JFrame(TestAnimation2.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
final JLabel label = new JLabel(new ImageIcon(new URL("http://www.lemondedemario.fr/images/dossier/bowser/bowser.png")));
label.setSize(label.getPreferredSize());
frame.setMinimumSize(label.getPreferredSize());
frame.add(label);
frame.setSize(WIDTH, HEIGHT);
dx = getNextSpeed();
dy = getNextSpeed();
Timer t = new Timer(1000 / NB_OF_IMAGES_PER_SECOND, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
x += dx;
y += dy;
if (x + label.getWidth() > frame.getContentPane().getWidth()) {
x = frame.getContentPane().getWidth() - label.getWidth();
dx = -getNextSpeed();
} else if (x < 0) {
x = 0;
dx = getNextSpeed();
}
if (y + label.getHeight() > frame.getContentPane().getHeight()) {
y = frame.getContentPane().getHeight() - label.getHeight();
dy = -getNextSpeed();
} else if (y < 0) {
y = 0;
dy = getNextSpeed();
}
label.setLocation((int) x, (int) y);
}
});
frame.setVisible(true);
t.start();
}
private double getNextSpeed() {
return 2 * Math.PI * (0.5 + random.nextDouble());
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
new TestAnimation2().initUI();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
Upvotes: 5