Java2d 中的动画图像
Animate Image in Java2d
我正在学习 Java2d,我正在尝试使用计时器在 x 坐标中为我的图像设置动画,但是没有用,这个想法是在一个时间帧之间,图像 x 值递增一个值使其移动,有人可以算出我的代码有什么问题?
代码如下:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class Screen extends JPanel {
int posX;
Timer timer;
private BufferedImage image;
public Screen() {
setDoubleBuffered(true);
posX = 1;
timer = new Timer();
timer.scheduleAtFixedRate(new Anima(), 100, 10);
//Smile Icon
try{
image = ImageIO.read(getClass().getResource("/smily.png"));
}catch(IOException e){
e.printStackTrace();
}
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image,this.posX,100,null);
}
class Anima extends TimerTask{
public void run() {
posX += 20;
repaint();
}
}
public void incMove() {
posX += 20;
}
}
您的代码可以正常工作,但您的更新速度太快了。
尝试
timer.scheduleAtFixedRate(new Anima(), 100, 1000);
检查你的动画。
两个主要的东西:
- 延迟小
- 变化大
这意味着可以将对象快速移出可见边界,通常比在屏幕上实现屏幕更快。
您可以控制时间,但是,动画是随时间变化的错觉,您可能会发现减少变化的大小比延迟更好(尽管 100fps 可能要求有点高; ))
也没有边界检查,所以对象可以自由地离开可视区域,这可能是可取的,但可能至少会提示您遇到的问题。
由于 Swing 不是线程安全的(您不应该从 EDT 上下文之外更新 UI),您还 运行 存在线程竞争条件的风险。在这个例子中,这可能很难做到,但是你如何改变状态的概念是危险的。
因为 Swing 使用被动渲染引擎,绘制周期可能随时发生,而无需您的交互或知识,因此您应该小心更新绘制方法需要在 EDT 上下文之外呈现状态的变量.
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 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 Screen extends JPanel {
public static void main(String[] args) {
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 Screen());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private int posX;
private int delta = 2;
public Screen() {
setDoubleBuffered(true);
posX = 1;
Timer timer = new Timer(10, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
incMove();
repaint();
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2d = (Graphics2D) g;
g2d.drawRect(this.posX, 100, 10, 10);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void incMove() {
posX += delta;
if (posX + 10 > getWidth()) {
posX = getWidth() - 10;
delta *= -1;
} else if (posX < 0) {
posX = 0;
delta *= -1;
}
}
}
这个简单的示例使用 Swing Timer
作为主要引擎,它减少了更改量(至 2
)并添加了边界检查
查看 Concurrency in Swing and How to use Swing Timers 了解更多详情
我正在学习 Java2d,我正在尝试使用计时器在 x 坐标中为我的图像设置动画,但是没有用,这个想法是在一个时间帧之间,图像 x 值递增一个值使其移动,有人可以算出我的代码有什么问题?
代码如下:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class Screen extends JPanel {
int posX;
Timer timer;
private BufferedImage image;
public Screen() {
setDoubleBuffered(true);
posX = 1;
timer = new Timer();
timer.scheduleAtFixedRate(new Anima(), 100, 10);
//Smile Icon
try{
image = ImageIO.read(getClass().getResource("/smily.png"));
}catch(IOException e){
e.printStackTrace();
}
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image,this.posX,100,null);
}
class Anima extends TimerTask{
public void run() {
posX += 20;
repaint();
}
}
public void incMove() {
posX += 20;
}
}
您的代码可以正常工作,但您的更新速度太快了。
尝试
timer.scheduleAtFixedRate(new Anima(), 100, 1000);
检查你的动画。
两个主要的东西:
- 延迟小
- 变化大
这意味着可以将对象快速移出可见边界,通常比在屏幕上实现屏幕更快。
您可以控制时间,但是,动画是随时间变化的错觉,您可能会发现减少变化的大小比延迟更好(尽管 100fps 可能要求有点高; ))
也没有边界检查,所以对象可以自由地离开可视区域,这可能是可取的,但可能至少会提示您遇到的问题。
由于 Swing 不是线程安全的(您不应该从 EDT 上下文之外更新 UI),您还 运行 存在线程竞争条件的风险。在这个例子中,这可能很难做到,但是你如何改变状态的概念是危险的。
因为 Swing 使用被动渲染引擎,绘制周期可能随时发生,而无需您的交互或知识,因此您应该小心更新绘制方法需要在 EDT 上下文之外呈现状态的变量.
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 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 Screen extends JPanel {
public static void main(String[] args) {
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 Screen());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private int posX;
private int delta = 2;
public Screen() {
setDoubleBuffered(true);
posX = 1;
Timer timer = new Timer(10, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
incMove();
repaint();
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2d = (Graphics2D) g;
g2d.drawRect(this.posX, 100, 10, 10);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void incMove() {
posX += delta;
if (posX + 10 > getWidth()) {
posX = getWidth() - 10;
delta *= -1;
} else if (posX < 0) {
posX = 0;
delta *= -1;
}
}
}
这个简单的示例使用 Swing Timer
作为主要引擎,它减少了更改量(至 2
)并添加了边界检查
查看 Concurrency in Swing and How to use Swing Timers 了解更多详情