2009-10-01 2 views
1

이 응용 프로그램의 최종 목표는 각 항목에 대한 스레드를 사용하여 동일한 속도의 다른 JPanel에서 여러 항목에 애니메이션을 적용하는 것입니다.하지만 첫 번째 부분은 완료되지만 항목은 동일하게 이동합니다 속도와 나는이 문제를 해결하는 방법에 대해 전혀 모른다.간단한 2 차원 애니메이션을위한 자바 스윙의 멀티 스레딩

package javagamestutos; 



import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Toolkit; 
import java.util.ArrayList; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JPanel; 


public class Board extends JPanel implements Runnable { 


    private Star star; 
    private Thread animator; 
    ArrayList<Star> items=new ArrayList<Star>(); 


    public Board() { 
     setBackground(Color.BLACK); 
     setDoubleBuffered(true); 
     star=new Star(25,0,0); 
     Star star2=new Star(50,20,25); 
     items.add(star2); 
     items.add(star); 
    } 

    public void addNotify() { 
     super.addNotify(); 
     animator = new Thread(this); 
     animator.start(); 
    } 

    public void paint(Graphics g) { 
     super.paint(g); 

     Graphics2D g2d = (Graphics2D)g; 



     for (Star s : this.items) { 
      g2d.drawImage(s.starImage, s.x, s.y, this); 
     } 


     Toolkit.getDefaultToolkit().sync(); 
     g.dispose(); 
    } 

    public void run() { 

     while(true){ 
      try { 
       for (Star s : this.items) { 
        s.move(); 
       } 
       repaint(); 

       Thread.sleep(star.delay); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Board.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 


} 

여기는 움직이는 항목 인 별표입니다. ?

package javagamestutos; 
import javax.swing.JFrame; 

public class Skeleton extends JFrame { 

public Skeleton() { 
     add(new Board()); 
     setTitle("Stars"); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setSize(300, 280); 
     setLocationRelativeTo(null); 
     setVisible(true); 
     setResizable(false); 
    } 
    public static void main(String[] args) { 
     new Skeleton(); 
    } 
} 

이 어떻게 내 목표를 달성하기 위해 내가 proprely 스레드를 사용하고 어떤 생각을 가지고 수행

package javagamestutos; 

import java.awt.Image; 
import javax.swing.ImageIcon; 

/** 
* 
* @author fenec 
*/ 
public class Star { 
    Image starImage; 
    int x,y; 
    int destinationX=200,destinationY=226; 
    boolean lockY=true; 
    int delay; 


    public Star(int delay,int initialX,int initialY){ 
     ImageIcon ii = new ImageIcon(this.getClass().getResource("star.png")); 
     starImage = ii.getImage(); 
     x=initialX; 
     y=initialY; 
     this.delay=delay; 
    } 


    void moveToX(int destX){ 
     this.x += 1; 
    } 


    boolean validDestinatonX(){ 
     if(this.x==this.destinationX){ 
       this.lockY=false; 
       return true; 
      } 
     else 
      return false; 
    } 

    void moveToY(int destY){ 
     this.y += 1; 
    } 


    boolean validDestinatonY(){ 
     if(this.y==this.destinationY) 
      return true; 
     else 
      return false; 
    } 

    void move(){ 

     if(!this.validDestinatonX()) 
      x+=1; 
     if(!this.validDestinatonY() && !this.lockY) 
      y+=1; 

     /*if(!this.validDestinatonY()) 
      y+=1; 
     */ 
    } 


} 

여기에는 JFrame의 확장 애니메이션의 골격입니까? 미리 감사드립니다.

답변

1

AWTDispatchThread에서 페인팅해야합니다. 그렇게하려면 SwingUtilities.invokeLater(Runnable);과 같은 것을 사용하고 싶을 것입니다. 이것은 애니메이션뿐만 아니라 여러분의 JFrame의 생성 및 설정에도 적용됩니다. 이 작업을 수행하지 않으면 페인팅 스레드에 교착 상태가 발생할 수 있습니다. 또한 페인팅 작업을 SwingUtilites 메서드로 옮길 때 while(true) 루프를 포함하지 않으므로 페인팅 스레드를 명령하게됩니다. 당신이 스레드에 페인트 하시겠습니까 경우

+0

"게시판이 Runnable이 아니므로 애니메이터 = 새 스레드 (컴파일)가 컴파일되지 않아야합니다." 어 ... 네. 'public class Board 확장 JPanel은 Runnable을 구현합니다' – Powerlord

+0

예, 귀하의 의견을 입력 할 때 편집했습니다. 일단 당신이 다시 포맷 한 것을 보았습니다. 너무 좋지 않은 게시물 편집을 upvote 수 있습니다. – akf

-1

, 당신은 사용할 수 있습니다 대신 재 페인트의

update(getGraphics()); 

합니다. 일반적으로 AWT 스레드에서 물건을 페인트 할 때 일반적으로 나쁜 습관으로 간주됩니다.

+0

@ 당신이 맞습니다. 그러나 그것이 같은 속도로 움직이는 이유는 아닙니다. – OscarRyz

+0

. 문제는 각 반복마다 일정한 시간을 자는데 있다고 생각합니다. 원하는 것은 객체를 가변 거리 (ctor에서 dx와 dy를 전달할 수 있음)로 이동하고 일정 시간 (예 : 25fps에서 40ms)을 잠자 게하는 것입니다. –

1

일반적으로, Swing 구성 요소는 AWT Event Dispatch Thread (EDT)에서 사용해야합니다. repaint은 EDT에서 사용할 수있는 방법 중 하나입니다. 그러나 Star은 스레드로부터 안전하지 않아야하며, 스레드로부터 안전하지 않아야합니다.

가장 쉬운 방법은 EDT 전용으로 시작하는 것입니다 (적어도 시작하는 것이 좋습니다). Thread 대신에 EDT에서 발생하는 javax.swing.Timer을 사용하십시오.

기타 설명 : paint 메서드를 사용하면 전송 된 그래픽 개체를 처리하거나 Toolkit을 사용하여 동기화 할 필요가 없습니다. 구성 요소를 이중 버퍼로 설정할 필요는 없지만 불투명으로 설정해야합니다 (JPanel은 불투명하다는 보장은 없습니다). 패널이 아니기 때문에 JPanel 대신 JComponent을 확장해야합니다. 일반적으로 외부 클래스가 Runnable을 구현하는 것은 좋은 생각이 아닙니다. 개인 변수 선호. 당신이 그들에게 모든 "N"밀리 초를 조금 이동하면 첫 번째의 지연에 의해 지정된 고정 된 속도로 "이동"메소드를 호출하고 있기 때문이다

2

그들은, 그래서

Thread.sleep(star.delay); 

을 "시작" 같은 평화로 움직일 것입니다.당신이 그 (것)들을 다른 속도로 이동하려면

, 당신은 마음에 omry에 의해 주석,

편집

I을 베어 (하나만 지금 사용하는) 다른 스레드에서 그들을 이동해야 그냥 비슷한 최근에 했어

나는 두 개의 다른 것들을 가지고있다. 그래서 나는 두 개의 타이머를 가지고있다. (타이머는 밑에 쓰레드를 사용하지만, 그들은 고정 된 속도로 실행 코드를 반복 할 수있다.)

제 ㄱ의 JLabel에 텍스트 매 초 (1000 MS)

final Timer timer = new Timer(); 
    timer.scheduleAtFixedRate(new TimerTask() { 
     public void run(){  
      setText(); 
     } 
    }, 0, 1000); 

다른 변화는 10 초마다 (10,000 MS)가

final Timer imageTimer = new Timer(); 
    imageTimer.scheduleAtFixedRate(new TimerTask() { 
     public void run() { 
      setImage(); 
     } 
    }, 0, 10000); 

I가 비디오를 가지고있는 화상 표시를 적용 여기 결과 :

enter image description here

고급 (그리고 좋은) 시간 관리를 위해서는 타이머에 추가 기능을 추가하는 "Timing Framework" 프로젝트를 반드시 살펴야합니다.

+0

+1 질문에 답하십시오. :) 단일 스레드를 사용할 수 있지만 우선 순위 큐를 사용하여 이동할 다음 별을 찾거나 다른 임의의 알고리즘 (위치를 저장하는 대신 시간을 계산하는 것과 같이)을 사용할 수 있습니다. –

1

난 당신이 그냥을 수행하는 오픈 소스 라이브러리 trident을 살펴 제안, 저자, 키릴 Grouchnikov라는 (그는 유명한 물질 모양 & 느낌의 저자) 스윙 세계에 잘 알려져있다.

트라이던트는 서로 다른 속도로 움직이는 문제를 해결하는 데 도움이됩니다. 결국 개체 당 하나의 스레드를 만들지 않아도됩니다 (결국 문제입니다).