2013-02-25 2 views
-1

Java의 repaint() 메소드에 문제가 있습니다. 나는 끊임없이 화면을 다시 칠하는 새로운 실을 만들었다. 스페이스 바를 놓을 때 위치를 설정하고 50 밀리 초를 기다리며 20 번 반복하면서 플레이어가 원활하게 떨어지길 원합니다. 대신, 루프의 전체 시간을 기다리는 다음 다시 칠합니다. 나는 왜 그것이 플레이어 코디네이트의 변화를 끊임없이 다시 그리지 않는지 궁금하다. 고맙습니다.Java repaint() 메소드가 항상 작동하지 않는 경우

(편집) 도움을 주신 모든 분들께 감사드립니다. 이것은 스택 오버플로를 사용하는 첫 번째 시간이며, 나는 단지 13 일 뿐이고 여전히 자바를 배우기 때문에 다시 자습서로 돌아갈 것입니다.

내 '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

+0

코드를 읽으려면 코드 형식을 올바르게 지정해야합니다. 몇 가지 제안. 1) 스윙 타이머를 사용하여 애니메이션을 원하십니까? 2) 사용자 정의 페인트는 paint() 메소드가 아니라 paintComponent() 메소드를 대체하여 수행됩니다. – camickr

+0

JPanel 클래스에서 실행 파일을 당겨 코드를 분리 해 보았습니다. 사실 이것은 단지 좋은 습관 일뿐 아니라 문제를 조금 더 시각화하는 데 도움이된다는 것을 알 수 있습니다. – christopher

답변

0

repaint은 가능한 한 빨리 페인트하기위한 "요청"일뿐입니다. 그래서 당신이 그것을 호출 할 때 가능한 한 빨리 paint 메소드를 호출합니다. here

에서

그래서 기본적으로 당신은 단지 paint 또는 while(true) repaint();update의 예약 전화를 홍수. 당신이 그것을 할 수있는, 또는 내가 그것을 얼마나 말을해야

Oracle's stance on painting in AWT and Swing

한 가지 방법은, 당신의 c 클래스는 키를 누를 때 있도록 KeyListener을 구현하는 것입니다 (그리고에만 눌렀을 때) 당신은 그것의 위치를 ​​업데이트합니다.

그래서 당신의 클래스 B의 생성자에서 당신은 전화 this.addKeyListener(player)를 추가하거나 추가하는 방법 void addPlayer(c player)을 만들 수 있습니다, 클래스 cKeyListener 방법을 이동합니다.

+0

도움을 주셔서 감사합니다. –

5

내가 여기에 여기에 모든 코드를 겪었지만하지 않은 몇 가지 포인터 :

  • 스윙은 UI 업데이트를 처리 할 수 ​​있도록 concurrency mechanisms 자신이있다. Thread이 아닌 Swing Timer을 사용할 수 있습니다. 관련은 Thread.sleep의 사용입니다 -이 작업을 수행하지 말고 EDT만을 차단하고 UI 업데이트를 차단합니다.
  • 스윙 페인트 체인 메커니즘은 paint 대신 paintComponent을 무시해야합니다.
  • 스윙에서 항상 KeyListeners이 아닌 Key Bindings을 사용하십시오. KeyListenersKeyEvents과 상호 작용하기 위해 구성 요소 포커스가 필요합니다. Key Bindings에는이 제한이 없습니다.
+0

+1, 당신은 내가했던 것보다 더 잘하고 링크를 포함한다고 말했습니다. – camickr

+0

모든 코드에 대해 도움을 주셔서 감사합니다. 나는이 문제를 보지 않을 것이라고 생각했다. –

+0

문제는 아니지만 스윙 타이머를 사용해보십시오 .... :) – Reimeus

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); 
} 

는 시스템 제어를 포기하지 않습니다. 스윙 타이머를 사용하여 다시 작성하십시오. 이것을 사용하는 방법에 대한 소개는 this tutorial을보십시오.

또한, 지속적으로 꽉 루프에서 repaint()를 호출 스레드 :

public void run(){ 
    while(true) repaint(); 
} 

끔찍한 생각이다. repaint()에 전체 CPU 속도로 전화 할 필요가 없습니다. 30 밀리 초마다 한 번 애니메이션에 적합합니다. Swing 유틸리티를 사용하여 루핑 스레드를 작성하는 대신이 작업을 수행하십시오.

+0

도움을 주셔서 감사합니다. –

관련 문제