[英]Java AWT/Swing When to use repaint() method?
我编写了一个代码来生成Snake游戏中的“ snake”进行练习。 (以防您不熟悉蛇游戏中的蛇,它是一条5盒长的蛇,其头部(由JLabel创建)和身体部位(也由JLabel创建)在头部之后。)
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;
public class SnakeGameFrame extends JFrame {
Thread snakeThread;
GroundPanel p;
public SnakeGameFrame() {
super("Moving Snake!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p = new GroundPanel();
setContentPane(p);
setSize(400,400);
setVisible(true);
p.requestFocus();
snakeThread = new Thread(p);
snakeThread.start();
}
class GroundPanel extends JPanel implements Runnable{
static final int LEFT = 0;
static final int RIGHT = 1;
static final int UP = 2;
static final int DOWN = 3;
int direction;
Image img;
SnakeBody snakeBody;
final int delay = 200;
public GroundPanel() {
setLayout(null);
snakeBody = new SnakeBody();
snakeBody.addIn(this);
direction = LEFT;
this.addKeyListener(new MyKeyListener());
ImageIcon icon = new ImageIcon("twilight.jpg");
img = icon.getImage();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0,0,getWidth(), getHeight(), null);
}
public void run() {
while(true) {
try {
Thread.sleep(delay);
snakeBody.move(direction);
}catch(InterruptedException e) {
return;
}
}
}
class MyKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT:
direction = LEFT;
break;
case KeyEvent.VK_RIGHT:
direction = RIGHT;
break;
case KeyEvent.VK_UP:
direction = UP;
break;
case KeyEvent.VK_DOWN:
direction = DOWN;
break;
}
}
}
}
class SnakeBody {
Vector<JLabel> v = new Vector<JLabel>();
public SnakeBody() {
ImageIcon head = new ImageIcon("head.jpg");
JLabel la = new JLabel(head);
la.setSize(head.getIconWidth(), head.getIconHeight());
la.setLocation(100, 100);
v.add(la);
ImageIcon body = new ImageIcon("body.jpg");
for(int i=1; i<10; i++) {
la = new JLabel(body);
la.setSize(body.getIconWidth(), body.getIconHeight());
la.setLocation(100+i*20, 100);
v.add(la);
}
}
public void addIn(JPanel p) {
for(int i=0; i<v.size(); i++)
p.add(v.get(i));
}
public void move(int direction) {
for(int i=v.size()-1; i>0; i--) {
JLabel b = v.get(i);
JLabel a = v.get(i-1);
b.setLocation(a.getX(), a.getY());
}
JLabel head = v.get(0);
switch(direction) {
case GroundPanel.LEFT :
head.setLocation(head.getX()-20, head.getY());
break;
case GroundPanel.RIGHT :
head.setLocation(head.getX()+20, head.getY());
break;
case GroundPanel.UP :
head.setLocation(head.getX(), head.getY()-20);
break;
case GroundPanel.DOWN :
head.setLocation(head.getX(), head.getY()+20);
break;
}
}
}
public static void main(String[] args) {
new SnakeGameFrame();
}
}
我的问题是为了继续“更新”我的蛇,我以为我必须在我的蛇中使用repaint()方法
公共无效run()
方法。 像这样
尝试{Thread.sleep(delay); snakeBody.move(direction); repaint(); }
但是事实证明,没有它也可以正常工作。我已经阅读了许多有关repaint()的文章,但是当我需要使用它时我仍然听不懂。 谁能用菜鸟友好的术语解释一下? 谢谢 :)
每当RepaintManager
尚未代表您调用repaint()
时,就必须调用它,例如通过更新绑定属性(例如,文本或颜色)。 在您的示例中,更改JLabel
的大小和位置会自动触发重新绘制。
更严重的是,您的示例通过两种方式错误地同步:
而是使用javax.swing.Timer
来调整动画的速度。 您的actionPerformed()
将在事件分配线程上调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.