Java JFrame中的精灵表动画
我正在尝试使用JFrame中的精灵表获取动画。问题是一旦加载,图像就不会改变。它只显示第一个图像。 我已经搜索了很多,尝试了几乎所有的建议,但都没有成功 顺便说一下,getSprite有一个返回类型的图像。 当我在JFrame中执行所有操作时,只显示一个图像。当我在扩展JPanel的单独类中执行此操作时,我只得到一个白色窗口 更新1:感谢andrew,JFrame工作正常。也修复了我的旧部分。这是工作表 更新2: 这是我的定时器版本Java JFrame中的精灵表动画,java,swing,animation,jframe,paintcomponent,Java,Swing,Animation,Jframe,Paintcomponent,我正在尝试使用JFrame中的精灵表获取动画。问题是一旦加载,图像就不会改变。它只显示第一个图像。 我已经搜索了很多,尝试了几乎所有的建议,但都没有成功 顺便说一下,getSprite有一个返回类型的图像。 当我在JFrame中执行所有操作时,只显示一个图像。当我在扩展JPanel的单独类中执行此操作时,我只得到一个白色窗口 更新1:感谢andrew,JFrame工作正常。也修复了我的旧部分。这是工作表 更新2: 这是我的定时器版本 class TestSpriteSheet extends J
class TestSpriteSheet extends JFrame{
//same old variables
public TestSpriteSheet(){
//same old stuff goes here before this
add(new PanelSprite(this, ss));
this.setVisible(true);
}
}
class PanelSprite extends JPanel{
private long runningTime = 0;
private int fps = 3;
private boolean stop = false;
private SpriteSheetManager ss;
private TestSpriteSheet temp;
public PanelSprite(TestSpriteSheet test, SpriteSheetManager sm){
ss = sm;
temp = test;
setSize(180,180);
setLayout(new BorderLayout()); init();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
long time = 5000;
animate_with_gfx(g, time);
}
public void init(){
Timer t = new Timer((int)(1000/fps), new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!stop) {
repaint();
} else {
((Timer)e.getSource()).stop();
}
}
});
t.setRepeats(true);
t.setDelay((int)(1000/fps));
t.start();
}
public void animate_with_gfx(Graphics g, long time){
if(runningTime <= time){
try {
System.out.println(runningTime); //Checking if this part works
int x = 0; int y = 0;
g.drawImage(ss.getSprite(x, y), 40, 40, null);
x++; y++; runningTime+=(1000/fps);
}catch (Exception ex) {
ex.printStackTrace();
}
}
else{
stop = true;
}
}
}
类TestSpriteSheet扩展JFrame{
//相同的旧变量
公共测试SpriteSheet(){
//以前这里也有同样的东西
添加(新PanelSprite(此,ss));
此.setVisible(true);
}
}
类PanelSprite扩展了JPanel{
私有长运行时间=0;
私有整数fps=3;
私有布尔停止=false;
私人SpriteSheetManager ss;
专用测试SpriteSheet temp;
公共面板Sprite(测试SpriteSheet测试,SpriteSheetManager sm){
ss=sm;
温度=试验;
设置大小(180180);
setLayout(新的BorderLayout());init();
}
公共组件(图形g){
超级组件(g);
长时间=5000;
使用_gfx(g,时间)设置_动画;
}
公共void init(){
计时器t=新计时器((int)(1000/fps),新ActionListener(){
已执行的公共无效操作(操作事件e){
如果(!停止){
重新油漆();
}否则{
((计时器)e.getSource()).stop();
}
}
});
t、 设置重复(真);
t、 设置延迟((整数)(1000/fps));
t、 start();
}
public void使用_gfx设置_动画(图形g,长时间){
if(运行时)
这部分完全错误,因为只要JRE认为视图需要重新绘制,就会调用paintComponent()
方法。所以一定要删除系统。退出(0);
然后计时器需要一个实例,启动一次。这最好在构造函数或init()
type方法中完成
它可能看起来像这样:
private int fps = 3;
private boolean stop = false;
public void paintComponent(Graphics g){
super.paintComponent(g);
long time = 5000;
animate_with_gfx(g, time, fps, stop);
}
/** Called from constructor.. */
public void init(){
Timer t = new Timer((int)(1000/fps), new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!stop) {
repaint();
} else {
((Timer)e.getSource()).stop();
}
}
});
t.setRepeats(true);
t.setDelay((int)(1000/fps));
t.start();
}
更新
import java.awt.*;
导入java.awt.image.buffereImage;
导入java.awt.event.*;
导入javax.swing.*;
导入java.io.IOException;
导入java.net.URL;
导入javax.imageio.imageio;
类SpriteSheetManager{
专用缓冲图像精灵表;
int cols;
int行;
公共SpriteSheetManager(){
setpritesheet();
}
公共无效设置价格表(){
试一试{
spriteSheet=ImageIO.read(
新网址(“http://s8.postimg.org/vso6oed91/spritesheet.png"));
setColsAndRows(3,3);
}捕获(IOE异常){
e、 printStackTrace();
}
}
公共缓冲区映像getSpriteSheet(){
返回精灵表;
}
public void setColsAndRows(int cols,int rows){
this.cols=cols;
this.rows=行;
}
公共图像getSprite(整数x,整数y){
图像精灵=空;
试一试{
sprite=spriteSheet.getSubimage(
x*spriteSheet.getWidth()/cols,
y*spriteSheet.getHeight()/行,
spriteSheet.getWidth()/cols,
spriteSheet.getHeight()/行);
}捕获(例外e){
e、 printStackTrace();
}
返回精灵;
}
}
表意文字{
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
新的TestSpriteSheet();
}
});
}
}
类TestSpriteSheet扩展了JFrame{
私有静态最终长serialVersionUID=1L;
私人SpriteSheetManager ss;
公共测试SpriteSheet(){
超级(“测试精灵表”);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
可设置大小(假);
setLayout(新的BorderLayout());
addWindowListener(新的WindowAdapter(){
公共作废窗口关闭(WindowEvent WindowEvent){
系统出口(0);
}
});
ss=新的SpriteSheetManager();
添加(新PanelSprite(此,ss));
包装();
设置大小(200200);
此.setVisible(true);
}
}
类PanelSprite扩展了JPanel{
私有长运行时间=0;
私人整数fps=10;
私有布尔停止=false;
私人SpriteSheetManager ss;
专用测试SpriteSheet temp;
私人定时器t;
整数计数=0;
长时间=50000;
公共面板Sprite(测试SpriteSheet测试,SpriteSheetManager sm){
ss=sm;
温度=试验;
init();
}
公共组件(图形g){
超级组件(g);
使用_gfx(g)设置_动画;
}
公共void init(){
t=新计时器((int)(1000/fps),新ActionListener(){
已执行的公共无效操作(操作事件e){
如果(!停止){
重新油漆();
}否则{
((计时器)e.getSource()).stop();
}
}
});
t、 设置重复(真);
t、 设置延迟((整数)(1000/fps));
t、 start();
}
公共空间使用_gfx设置_动画(图形g){
如果(runningTime)我删除了System.exit(0),但什么也没发生。你能详细说明一下“那么计时器需要一个实例,只启动一次。这最好在构造函数或init()类型方法中完成。”?不,它仍然不会更改图像。更新了问题。setLayout(new BorderLayout());}
应该是setLayout(new BorderLayout());init();}
。这就是从构造函数调用的意思!是的,但图像没有改变。1)为了更快地获得更好的帮助,发布(最小完整的可验证示例)或
private int fps = 3;
private boolean stop = false;
public void paintComponent(Graphics g){
super.paintComponent(g);
long time = 5000;
animate_with_gfx(g, time, fps, stop);
}
/** Called from constructor.. */
public void init(){
Timer t = new Timer((int)(1000/fps), new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!stop) {
repaint();
} else {
((Timer)e.getSource()).stop();
}
}
});
t.setRepeats(true);
t.setDelay((int)(1000/fps));
t.start();
}
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import javax.swing.*;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
class SpriteSheetManager {
private BufferedImage spriteSheet;
int cols;
int rows;
public SpriteSheetManager() {
setSpriteSheet();
}
public void setSpriteSheet() {
try {
spriteSheet = ImageIO.read(
new URL("http://s8.postimg.org/vso6oed91/spritesheet.png"));
setColsAndRows(3, 3);
} catch (IOException e) {
e.printStackTrace();
}
}
public BufferedImage getSpriteSheet() {
return spriteSheet;
}
public void setColsAndRows(int cols, int rows) {
this.cols = cols;
this.rows = rows;
}
public Image getSprite(int x, int y) {
Image sprite = null;
try {
sprite = spriteSheet.getSubimage(
x * spriteSheet.getWidth() / cols,
y * spriteSheet.getHeight() / rows,
spriteSheet.getWidth() / cols,
spriteSheet.getHeight() / rows);
} catch (Exception e) {
e.printStackTrace();
}
return sprite;
}
}
class Ideone {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestSpriteSheet();
}
});
}
}
class TestSpriteSheet extends JFrame {
private static final long serialVersionUID = 1L;
private SpriteSheetManager ss;
public TestSpriteSheet() {
super("Testing SpriteSheets");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setLayout(new BorderLayout());
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent) {
System.exit(0);
}
});
ss = new SpriteSheetManager();
add(new PanelSprite(this, ss));
pack();
setSize(200, 200);
this.setVisible(true);
}
}
class PanelSprite extends JPanel {
private long runningTime = 0;
private int fps = 10;
private boolean stop = false;
private SpriteSheetManager ss;
private TestSpriteSheet temp;
private Timer t;
int count = 0;
long time = 50000;
public PanelSprite(TestSpriteSheet test, SpriteSheetManager sm) {
ss = sm;
temp = test;
init();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
animate_with_gfx(g);
}
public void init() {
t = new Timer((int) (1000 / fps), new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!stop) {
repaint();
} else {
((Timer) e.getSource()).stop();
}
}
});
t.setRepeats(true);
t.setDelay((int) (1000 / fps));
t.start();
}
public void animate_with_gfx(Graphics g) {
if (runningTime <= time) {
Image img = ss.getSprite((count % 9) % 3, (count % 9) / 3);
g.drawImage(img, 40, 40, this);
count++;
runningTime += (1000 / fps);
} else {
stop = true;
}
}
}