将action方法移至FishAnimation类后Java Swing动画失效求助
问题:动画逻辑迁移到FishAnimation类后失效
将原本在Screen类中的动画action方法剪切到FishAnimation类后,调用fA.action()完全看不到动画效果,但把方法移回Screen类就正常运行,请问原因是什么?
Screen类代码
package main; import java.awt.Dimension; import java.io.IOException; import javax.swing.JFrame; import javax.swing.JLayeredPane; import javax.swing.JPanel; import AnimatorHandler.FishAnimation; import data.*; import save.Data; public class Screen extends JPanel{ Resources res = new Resources(); Background background = new Background(); Ground ground = new Ground(); Animal animal = new Animal(null, null, 0, null, 0, 0); FishAnimation fA = new FishAnimation(); int screenSizeX = 1099; int screenSizeY = 735; void createWindow() throws IOException { //CREATION OF THE RESOURCES background.createBackground(); ground.createGround(); animal.createAnimal(); //SETTING OF THE LAYEREDPANE JLayeredPane layeredPane = new JLayeredPane(); layeredPane.setBounds(0, 0, screenSizeX, screenSizeY); layeredPane.add(background.background[Data.selectedBackground], Integer.valueOf(0)); layeredPane.add(ground.ground[Data.selectedGround], Integer.valueOf(1)); layeredPane.add(animal.animals[Data.selectedAnimal], Integer.valueOf(2)); layeredPane.add(animal.animals[Data.selectedAnimal+1], Integer.valueOf(2)); //SETTING OF THE FRAME JFrame frame = new JFrame("Happy Aquarium"); frame.add(layeredPane); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(new Dimension(screenSizeX, screenSizeY)); frame.setLayout(null); frame.setVisible(true); //ANIMATION fA.action(); } }
FishAnimation类代码
package AnimatorHandler; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.Timer; import data.Animal; import save.Data; public class FishAnimation implements ActionListener{ Animal animal = new Animal(null, null, 0, null, 0, 0); Timer timer; public void action() throws IOException { animal.createAnimal(); timer = new Timer(1, this); timer.start(); } @Override public void actionPerformed(ActionEvent e) { if(animal.animals[Data.selectedAnimal].getY() >= 260 || animal.animals[Data.selectedAnimal].getY()<-300) { animal.animali[Data.selectedAnimal].setYVelocity(animal.animali[Data.selectedAnimal].getYVelocity() * -1); } if(animal.animals[Data.selectedAnimal].getX() >= 456 || animal.animals[Data.selectedAnimal].getX()<-456) { animal.animali[Data.selectedAnimal].setXVelocity(animal.animali[Data.selectedAnimal].getXVelocity() * -1); } animal.animals[Data.selectedAnimal].setBounds(animal.animals[Data.selectedAnimal].getX() + animal.animali[Data.selectedAnimal].getXVelocity(), animal.animals[Data.selectedAnimal].getY() + animal.animali[Data.selectedAnimal].getYVelocity(), 1083, 696); if(animal.animals[Data.selectedAnimal+1].getY() >= 260 || animal.animals[Data.selectedAnimal+1].getY()<-300) { animal.animali[Data.selectedAnimal+1].setYVelocity(animal.animali[Data.selectedAnimal+1].getYVelocity() * -1); } if(animal.animals[Data.selectedAnimal+1].getX() >= 456 || animal.animals[Data.selectedAnimal+1].getX()<-456) { animal.animali[Data.selectedAnimal+1].setXVelocity(animal.animali[Data.selectedAnimal+1].getXVelocity() * -1); } animal.animals[Data.selectedAnimal+1].setBounds(animal.animals[Data.selectedAnimal+1].getX() + animal.animali[Data.selectedAnimal+1].getXVelocity(), animal.animals[Data.selectedAnimal+1].getY() + animal.animali[Data.selectedAnimal+1].getYVelocity(), 1083, 696); } }
原因分析
核心问题是操作的对象不一致:
- Screen类中创建了一个
Animal实例,调用animal.createAnimal()后,将这个实例的动物组件添加到了UI的分层面板中,是界面上显示的真实对象。 - FishAnimation类内部自己new了一个全新的
Animal实例,这个实例和Screen里的不是同一个对象,它的组件从未被添加到界面上。 - FishAnimation的
actionPerformed方法一直在修改自己内部这个"隐形"的Animal实例的属性,界面上的真实组件完全没被改动,所以看不到动画效果;而原来在Screen类中时,操作的是同一个被添加到UI的Animal实例,所以动画正常。
修复方案
1. 修改FishAnimation类,接收外部传入的Animal实例
去掉内部自己创建的Animal,通过构造方法传入Screen中的实例:
package AnimatorHandler; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.Timer; import data.Animal; import save.Data; public class FishAnimation implements ActionListener{ private Animal animal; // 改为外部传入 Timer timer; // 新增构造方法,接收Animal实例 public FishAnimation(Animal animal) { this.animal = animal; } public void action() throws IOException { // 移除animal.createAnimal(),因为Screen中已经初始化过 timer = new Timer(1, this); timer.start(); } @Override public void actionPerformed(ActionEvent e) { // 方法内容保持不变,现在操作的是界面上的真实Animal实例 if(animal.animals[Data.selectedAnimal].getY() >= 260 || animal.animals[Data.selectedAnimal].getY()<-300) { animal.animali[Data.selectedAnimal].setYVelocity(animal.animali[Data.selectedAnimal].getYVelocity() * -1); } if(animal.animals[Data.selectedAnimal].getX() >= 456 || animal.animals[Data.selectedAnimal].getX()<-456) { animal.animali[Data.selectedAnimal].setXVelocity(animal.animali[Data.selectedAnimal].getXVelocity() * -1); } animal.animals[Data.selectedAnimal].setBounds(animal.animals[Data.selectedAnimal].getX() + animal.animali[Data.selectedAnimal].getXVelocity(), animal.animals[Data.selectedAnimal].getY() + animal.animali[Data.selectedAnimal].getYVelocity(), 1083, 696); if(animal.animals[Data.selectedAnimal+1].getY() >= 260 || animal.animals[Data.selectedAnimal+1].getY()<-300) { animal.animali[Data.selectedAnimal+1].setYVelocity(animal.animali[Data.selectedAnimal+1].getYVelocity() * -1); } if(animal.animals[Data.selectedAnimal+1].getX() >= 456 || animal.animals[Data.selectedAnimal+1].getX()<-456) { animal.animali[Data.selectedAnimal+1].setXVelocity(animal.animali[Data.selectedAnimal+1].getXVelocity() * -1); } animal.animals[Data.selectedAnimal+1].setBounds(animal.animals[Data.selectedAnimal+1].getX() + animal.animali[Data.selectedAnimal+1].getXVelocity(), animal.animals[Data.selectedAnimal+1].getY() + animal.animali[Data.selectedAnimal+1].getYVelocity(), 1083, 696); } }
2. 修改Screen类,初始化FishAnimation时传入自己的Animal实例
package main; import java.awt.Dimension; import java.io.IOException; import javax.swing.JFrame; import javax.swing.JLayeredPane; import javax.swing.JPanel; import AnimatorHandler.FishAnimation; import data.*; import save.Data; public class Screen extends JPanel{ Resources res = new Resources(); Background background = new Background(); Ground ground = new Ground(); Animal animal = new Animal(null, null, 0, null, 0, 0); FishAnimation fA; // 先声明,后初始化 int screenSizeX = 1099; int screenSizeY = 735; void createWindow() throws IOException { //CREATION OF THE RESOURCES background.createBackground(); ground.createGround(); animal.createAnimal(); // 初始化FishAnimation时传入当前的animal实例 fA = new FishAnimation(animal); //SETTING OF THE LAYEREDPANE JLayeredPane layeredPane = new JLayeredPane(); layeredPane.setBounds(0, 0, screenSizeX, screenSizeY); layeredPane.add(background.background[Data.selectedBackground], Integer.valueOf(0)); layeredPane.add(ground.ground[Data.selectedGround], Integer.valueOf(1)); layeredPane.add(animal.animals[Data.selectedAnimal], Integer.valueOf(2)); layeredPane.add(animal.animals[Data.selectedAnimal+1], Integer.valueOf(2)); //SETTING OF THE FRAME JFrame frame = new JFrame("Happy Aquarium"); frame.add(layeredPane); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(new Dimension(screenSizeX, screenSizeY)); frame.setLayout(null); frame.setVisible(true); //ANIMATION fA.action(); } }
内容的提问来源于stack exchange,提问作者TokenZ
相关产品推荐
相关产品推荐

