2013-02-25 90 views
-1

Java中的repaint()方法存在问题。我做了一个不断重新绘制屏幕的新线程。当我释放空格键时,我希望我的播放器能够通过设置其位置顺利地下滑,然后等待50毫秒并循环20次。相反,它等待循环中的整个时间量,然后然后重绘。我想知道为什么它不会不断重新绘制球员坐标的变化。谢谢。Java repaint()方法并不总是有效

(编辑)感谢大家的帮助。这是我第一次使用堆栈溢出,我只有13岁,仍然在学习java,所以我可能会再次回到教程。

我的 'A' 级(主):

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; 
    } 
} 
+4

对不起。这段代码真的很难阅读。你能把它切成什么绝对必要的吗?你刚刚打了一层代码。 – christopher 2013-02-25 16:22:16

+0

如果您希望我们阅读代码,那么代码应该正确格式化!几个建议。 1)使用摆动计时器是你想要的动画。 2)自定义绘画是通过覆盖paintComponent()方法而不是paint()方法来完成的。 – camickr 2013-02-25 16:23:39

+0

您是否尝试将runnable从JPanel类中拉出来并将代码分离出来?除此之外,这只是一个很好的做法,您可能会发现它可以帮助您更加直观地看到问题。 – christopher 2013-02-25 16:25:53

回答

0

repaint只是一个“请求”,尽快绘制。所以当你调用它时,它会尽快调用paint方法。

here

所以基本上你只是泛滥的paintupdatewhile(true) repaint();的排定呼叫。你能做到这一点,或者我应该说我会怎么做

Oracle's stance on painting in AWT and Swing

的方法之一,就是让你的c类实现KeyListener,这样,当有键按下(只有当它被按下)你更新它的位置。

所以你KeyListener方法移到c类,在B类的构造函数,你可以添加通话this.addKeyListener(player)或制作方法void addPlayer(c player),增加了它。

+0

感谢您的帮助。 – 2013-02-25 16:41:32

5

我没有经过这里所有的代码了,但这里有一些指点:

  • 秋千都有自己concurrency mechanisms,让你处理UI更新。您可以使用Swing Timer而不是原始Thread。相关的是使用Thread.sleep - 不要这样做,它只会阻止EDT并阻止UI更新。
  • Swing涂料链机制要求您覆盖paintComponent而不是paint
  • 在Swing中始终使用Key Bindings而不是KeyListenersKeyListeners需要组件重点才能与KeyEvents进行交互。 Key Bindings没有这个限制。
+0

+1,你说的比我更好,包括链接。 – camickr 2013-02-25 16:25:27

+0

感谢您的帮助,我对所有的代码感到抱歉。我不认为我会遇到这个问题。 – 2013-02-25 16:39:58

+0

没问题,试试Swing Timer虽然.... :) – Reimeus 2013-02-25 16:41:03

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实用程序来执行此操作,而不是编写自己的循环线程。

+0

感谢您的帮助。 – 2013-02-25 16:44:28

相关问题