我通过在前者之后几十毫秒绘制不同的图像来制作动画。像这样的东西:
drawimage(image1,0,0,null);
try {
Thread.sleep(100);
}catch(Exception e){//To do something
}
drawimage(image2,0,0,null);
但第一张图片在第二张图片出现之前不会显示。这意味着它们同时出现。
我的问题是为什么会发生这种情况?
答案 0 :(得分:1)
程序在当前状态下同时绘制两个图像,因为draw methods
中有两个loop
(如果你确实在使用循环)。
为了解决这个问题,您应该只使用一种绘制方法,并将延迟保留在同一位置。但是,为了遍历所有不同的图像变量(如果你在数组中将它们命名为数字1,2,3,4 ...等),你可以使用for循环来绘制它们:
for (int i = 0; i< *however many images you have*; i++){
drawimage(image[i],0,0,null);
try {
Thread.sleep(100);
}catch(Exception e){//To do something
}
}
修改
您不会在paintComponent
内使用延迟。既然你是,那就是可能导致问题的原因。将延迟移到程序的main
方法中。
答案 1 :(得分:1)
我:这段代码到底在哪里?它是在paint / paintComponent方法中吗?
OP:它位于paintComponent中。我用它来制作动画,但我不确定这是一个好方法。
你是对的,这不是一个好方法。 不要在Thread.sleep
方法中调用paintComponent
。我会一起避免使用Thread.sleep
并使用javax.swing.Timer
。查看更多How to Use Swing Timers
你可以......
使用list
Images
和Timer
事件的每次迭代触发,将另一个Image
添加到List<Image>
并致电repaint()
你可以......
拥有MyImage
对象类,其中包含Image
字段和boolean draw
字段。在Timer中,循环遍历MyImage
对象并执行类似
for (MyImage image: images) {
if (!image.isDraw()) {
image.setDraw(true);
break;
}
}
repaint();
MyImage
List
只需在paintComponent
方法中循环显示它们,并将其称为drawImage
方法即可。
运行此exmaple,显示第一个选项
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
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.SwingUtilities;
import javax.swing.Timer;
public class AnimateImages extends JPanel {
private static final int IMAGE_ROWS = 10;
private static final int IMAGE_COLS = 10;
private static final int IMAGE_SIZE = 50;
private static final int DIM_WIDTH = IMAGE_COLS * IMAGE_SIZE;
private final List<MyImage> images;
private Image image;
private int currX = -IMAGE_SIZE;
private int currY;
public AnimateImages() {
try {
image = ImageIO.read(new URL("http://swoo.co.uk/content/images/icons/stackoverflow.png"));
} catch (IOException ex) {
Logger.getLogger(AnimateImages.class.getName()).log(Level.SEVERE, null, ex);
}
images = createImages();
Timer timer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (MyImage image : images) {
if (!image.isDraw()) {
image.setDraw(true);
break;
}
repaint();
}
}
});
timer.start();
}
private List<MyImage> createImages() {
List<MyImage> list = new ArrayList<>();
for (int i = 0; i < IMAGE_ROWS * IMAGE_COLS; i++) {
if (currX >= DIM_WIDTH) {
currX = 0;
currY += IMAGE_SIZE;
} else {
currX += IMAGE_SIZE;
}
list.add(new MyImage(image, currX, currY));
}
return list;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (MyImage img : images) {
img.draw(g);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(IMAGE_SIZE * IMAGE_COLS, IMAGE_SIZE * IMAGE_ROWS);
}
public class MyImage {
Image image;
int x, y;
boolean draw = false;
public MyImage(Image image, int x, int y) {
this.image = image;
this.x = x;
this.y = y;
}
public void setDraw(boolean draw) {
this.draw = draw;
}
public boolean isDraw() {
return draw;
}
public void draw(Graphics g) {
if (draw) {
g.drawImage(image, x, y, IMAGE_SIZE, IMAGE_SIZE, AnimateImages.this);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new AnimateImages());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
答案 2 :(得分:0)
您的回答
您收到此结果是因为它正在打印image1
,等待.1秒然后再打印image2
。然后它不会等待,游戏立即更新,然后打印image1
。 image2
的展示时间是微观的,您可能只会看到image1
。
此外,图像永远不会被删除或替换,因此您不断地在彼此之上绘制图像,这会导致内存泄漏,并且可能是您看到两个图像的原因。
<强>考虑强>
这是我从this tutorial获得并仍然使用的一个方便的小动画类。这个类非常方便,你可以添加每个动画所需的动画精灵。
使用此课程,当您执行drawImage()
时,可以使用object.getImage()
提取动画的当前帧。
确保您在游戏的主循环中调用动画的update()
方法,以便不断更新动画。
import java.awt.Image;
import java.util.ArrayList;
public class Animation {
private ArrayList frames;
private int currentFrame;
private long animTime;
private long totalDuration;
public Animation() {
frames = new ArrayList();
totalDuration = 0;
synchronized (this) {
animTime = 0;
currentFrame = 0;
}
}
public synchronized void addFrame(Image image, long duration) {
totalDuration += duration;
frames.add(new AnimFrame(image, totalDuration));
}
public synchronized void update(long elapsedTime) {
if (frames.size() > 1) {
animTime += elapsedTime;
if (animTime >= totalDuration) {
animTime = animTime % totalDuration;
currentFrame = 0;
}
while (animTime > getFrame(currentFrame).endTime) {
currentFrame++;
}
}
}
public synchronized Image getImage() {
if (frames.size() == 0) {
return null;
} else {
return getFrame(currentFrame).image;
}
}
private AnimFrame getFrame(int i) {
return (AnimFrame) frames.get(i);
}
private class AnimFrame {
Image image;
long endTime;
public AnimFrame(Image image, long endTime) {
this.image = image;
this.endTime = endTime;
}
}
}