Java中的repaint()方法存在问题。我创建了一个不断重新绘制屏幕的新线程。当我释放空格键时,我希望我的播放器通过设置其位置然后等待50毫秒并循环20次来顺利下降。相反,它等待循环中的整个时间,然后重新绘制。我想知道为什么它不会不断重现球员坐标的变化。谢谢。
(编辑)感谢大家的帮助。这是我第一次使用堆栈溢出,而我只有13,仍在学习java,所以我可能会再次回到教程。
我的'一级'(主要):
public class a {
public static void main(String[] args) {
JFrame frame = new JFrame("StickFigure Game");
frame.setSize(740, 580);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
b board = new b();
frame.add(board);
frame.addKeyListener(board);
}
}
我的'b'级(JPanel /绘图):
public class b extends JPanel implements KeyListener {
c player = new c();
public class MyRunnable implements Runnable {
public void run() {
while (true)
repaint();
}
}
MyRunnable run = new MyRunnable();
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(player.getImage(), player.getX(), player.getY(), 80, 140,
null);
}
public b() {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
public static void slow(int n) {
long t0, t1;
t0 = System.currentTimeMillis();
do {
t1 = System.currentTimeMillis();
} while (t1 - t0 < n);
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_D) {
player.setPos(player.getX() + 6, player.getY());
}
if (e.getKeyCode() == KeyEvent.VK_A) {
player.setPos(player.getX() - 6, player.getY());
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
player.setPos(player.getX(), player.getY() - 60);
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
for (int i = 0; i < 20; i++) {
slow(50);
player.setPos(player.getX(), player.getY() + 2);
}
}
}
public void keyTyped(KeyEvent e) {
}
}
我的'c'级(球员):
public class c {
private ImageIcon i = new ImageIcon("guy.png");
private Image img = i.getImage();
private int x = 0;
private int y = 100;
public void wait(int what) {
try {
Thread.sleep(what);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public c() {
}
public Image getImage() {
return img;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setPos(int mx, int my) {
x = mx;
y = my;
}
}
答案 0 :(得分:5)
我没有完成所有代码,但这里有一些指示:
Thread
。相关的是使用Thread.sleep
- 不要这样做,它只会阻止EDT
并阻止UI更新。paintComponent
而不是paint
。KeyListeners
。 KeyListeners
需要重点关注组件才能与KeyEvents
进行互动。 Key Bindings
没有此限制。答案 1 :(得分:3)
“java中的repaint()方法存在问题。”您是否认为问题可能与您的代码有关?您正在阻止事件线程并使系统没有时间进行中间重新绘制。特别是这种方法:
public static void slow (int n){
long t0,t1;
t0=System.currentTimeMillis();
do{
t1=System.currentTimeMillis();
}
while (t1-t0<n);
}
和这个循环:
for(int i = 0;i<20;i++){
slow(50);
player.setPos(player.getX(), player.getY()+2);
}
不要放弃对系统的控制,以便重新涂抹实际上可以发生。使用Swing计时器重写那些。请查看this tutorial,了解如何使用这些内容。
此外,您的线程会在紧密循环中不断调用repaint()
:
public void run(){
while(true) repaint();
}
是个糟糕的主意。您无需以全CPU速度调用repaint()
。每30毫秒左右就可以完成一次动画。再次,考虑使用Swing实用程序来执行此操作,而不是编写自己的循环线程。
答案 2 :(得分:0)
repaint
只是一个“请求”,要尽快绘制。因此,当你调用它时,它会尽快调用paint方法。
来自here
所以基本上你只是用[{1}}充斥了paint
或update
的预定来电。
Oracle's stance on painting in AWT and Swing
你可以做到的一种方式,或者我应该怎么做,就是让你的while(true) repaint();
类实现c
,这样当按下一个键时(并且只有当它被按下时)按下)你更新它的位置。
因此,将您的KeyListener
方法移至课程KeyListener
,在您的b类构造函数中,您可以添加调用c
或制作添加它的方法this.addKeyListener(player)
。