Java 为什么动画没有更新?
} 我已经读了很多关于我的问题的答案,但我已经坚持了好几个小时了。如果Java 为什么动画没有更新?,java,animation,paintcomponent,Java,Animation,Paintcomponent,} 我已经读了很多关于我的问题的答案,但我已经坚持了好几个小时了。如果repaint()应该调用覆盖的paintComponent(),为什么我根本看不到动画?我的意思是大多数事情都可以工作:如果我把System.out.println(“test”)放进去,我可以看到线程正在工作,在调试模式下,我可以看到shipX和shipY值在变化,但在窗口中,图像卡在0,0坐标的开头。我一直在尝试一切,从覆盖paint()和重写这两个选项,但似乎没有什么可以让动画继续运行 有人能提供帮助吗?问题 Thr
repaint()
应该调用覆盖的paintComponent()
,为什么我根本看不到动画?我的意思是大多数事情都可以工作:如果我把System.out.println(“test”)
放进去,我可以看到线程正在工作,在调试模式下,我可以看到shipX
和shipY
值在变化,但在窗口中,图像卡在0,0坐标的开头。我一直在尝试一切,从覆盖paint()
和重写这两个选项,但似乎没有什么可以让动画继续运行
有人能提供帮助吗?问题
-Swing是单线程的,在事件调度线程(EDT)上运行。这就是画的地方。你基本上阻止了EDTThread.sleep()
-可能是对3的误解。是毫秒。3毫秒相当短。你基本上是在暗示你想要每秒300多帧。会很难的线程。睡眠(3)
- 创建两个
-用线程创建一个,然后在框架中添加一个不同的线程(这可能是最大的问题,但我会将thread.sleep放在它旁边)游戏面板
- 使用
代替swing动画。此计时器将在EDT上工作。更多信息请访问javax.swing.Timer
- 使用计时器时,请选择更合理的延迟。每秒25-30帧之间的速度比较好。因此,40毫秒的延迟大约是25 fps
- 不要创建两个
。就用一个游戏面板
定时器的基本结构
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
private static final long serialVersionUID = 1L;
private final int WIDTH = 400;
private final int HEIGHT = 400;
private static BufferedImage ship;
private int shipX;
private int shipY;
private boolean running;
public GamePanel(){
super();
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
try {ship = ImageIO.read(new File("res/ship2.png"));}
catch (IOException e) {e.printStackTrace();}
running = true;
}
private void gameUpdate() {
shipX++;
shipY++;
}
@Override
public void run() {
while(running){
gameUpdate();
repaint();
try {Thread.sleep(3);}
catch (InterruptedException e){e.printStackTrace();}
}
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, WIDTH, HEIGHT);
g.drawImage(ship, shipX, shipY, 100, 100, null);
}
}
import javax.swing.JFrame;
public class Game extends JFrame{
private static final long serialVersionUID = 1L;
public Game(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
GamePanel g = new GamePanel();
Thread t = new Thread(g);
t.start();
add(new GamePanel());
pack();
setVisible(true);
}
public static void main(String[] args) {
new Game();
}
从某种意义上讲,计时器的工作原理就像一个按钮,就它而言ActionListener
。每延迟几毫秒,它就会触发一个ActionEvent
,侦听器将捕获它,并调用它的actionPerformed
。请参阅链接以获得更好的解释。我现在太懒了,没法更彻底地了解
有关在EDT上运行应用程序的一些信息,请参阅。您应该将程序包装在一个
SwingUtilities.invokeLater(…)
应该是
g.drawImage(ship, shipX, shipY, 100, 100, null);
Java文档在学习绘画时非常有用,我建议您阅读它。下面是编辑的同一个演示,用于沿直线移动船舶,直到到达面板上的某个点
这可能不是你想要的答案,但这在我学习绘画时帮了我很大的忙
g.drawImage(ship, shipX, shipY, 100, 100, this);
^
|
The panel is the ImageObserver
什么
Thread
在列出的代码中没有创建新的Thread
。这个问题似乎离题了,因为这个代码有太多错误,需要一本书来解释。事实上,亚马逊上有很多书解释了这一切。我不确定这是否构成“离题”。300 FPS就可以了——问问任何玩家。但在这种情况下,图像将在大约1.3秒后消失,这对于这种动画来说可能有点短。。。同样值得添加到您的答案中-OP启动一个线程
,没有同步或可见性保证(在这里添加到swing并发教程的链接?)
g.drawImage(ship, shipX, shipY, 100, 100, null);
g.drawImage(ship, shipX, shipY, 100, 100, this);
^
|
The panel is the ImageObserver
package messaround;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Game {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
System.out.println("Created GUI on EDT? "+
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
}
class MyPanel extends JPanel {
BufferedImage boat;
Timer timer;
private int boatX = 0;
private int boatY = 0;
private int boatW;
private int boatH;
public MyPanel() {
try {
boat = ImageIO.read(new File("res/ship2.png"));
} catch (IOException e) {
e.printStackTrace();
}
boatW=boat.getWidth();
boatH=boat.getHeight();
timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
moveBoat();
if(boatX>100){
timer.cancel();
timer.purge();
}
}} ,0, 30);
setBorder(BorderFactory.createLineBorder(Color.black));
}
public void moveBoat(){
repaint(boatX,boatY,boatW,boatH);
boatX++;
boatY++;
repaint(boatX,boatY,boatW,boatH);
}
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(boat, boatX, boatY, this);
}
}