2014-05-08 33 views
-3

我已經制作了一個彈跳兩個球的程序,但是在運行程序時它只是顯示兩個球而他們沒有移動,我無法理解這是什麼問題? 在runnable開始時是否有任何問題,因爲當我只運行單個球時,它運行沒有實現Runnable接口,但它不適用於兩個爲什麼?球不動爲什麼?

 import java.awt.Color; 
     import java.awt.Graphics; 
     import java.awt.Graphics2D; 
     import java.awt.RenderingHints; 

     import javax.swing.JFrame; 
     import javax.swing.JPanel; 



     public class Jpanel extends JPanel implements Runnable{ 


     Thread t1; 
     Thread t2; 
     JFrame frame; 
     Jpanel jp; 
     int x=0; 
     int y=0; 
     Ball ball=new Ball(this); 
     Ball1 ball1=new Ball1(this); 
     void move1(){ 
      ball.move(); 

     } 
     void move2(){ 
      ball1.move(); 
     } 
     public void paint(Graphics g){ 


      super.paint(g); 
      setBackground(Color.black); 
      Graphics2D g2d=(Graphics2D)g; 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); 

      ball.paint(g); 
      ball1.paint(g); 
     //super.paint(g);//agar yaha to puri screen pehle jaisi saaf ho jaegi   
     } 


    public static void main(String args[]) throws InterruptedException{ 

     Jpanel jp=new Jpanel(); 
     JFrame frame =new JFrame("Chota Bheem"); 
     frame.add(jp); 
     frame.setBackground(Color.BLACK); 
     frame.setSize(500,500); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE); 
     Jpanel t1=new Jpanel(); 
     Jpanel t2=new Jpanel(); 
     t1.start(); 
     t2.start(); 






     } 
     public void start() { 
     System.out.println("inside start"); 
     // TODO Auto-generated method stub 
     if(t1==null){ 
      t1=new Thread(this,"first"); 
      t1.start(); 
     } 
     if(t2==null){ 
      t2=new Thread(this,"second"); 
      t2.start(); 
     } 

    } 
    @Override 
     public void run() { 
     // TODO Auto-generated method stub 
      System.out.println("inside run"); 
     while(true){ 
      jp.move1(); 
      jp.repaint(); 

      try { 
       Thread.sleep(1); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     while(true){ 
     jp.move2(); 
     jp.repaint(); 

     try { 
      Thread.sleep(1); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     } 
    } 
    } 



     class Ball1{ 
     Jpanel jps; 
     int x=0,y=0,xs=-1,ys=-1; 
     public Ball1(Jpanel jpanel) { 
     // TODO Auto-generated constructor stub 
     this.jps=jpanel; 

    } 
     public void move(){ 
     if(x+xs<0){xs=1;} 
     else if(y+ys<0){y=-1;} 
     else if(x+xs>jps.getWidth()-30){xs=-1;} 
     else if(y+ys>jps.getHeight()-30){ys=-1;} 

     x=x+xs; 
     y=y+ys; 

    } 
    void paint(Graphics g){ 
     g.setColor(Color.darkGray); 
     g.fillOval(x, y, 60, 60); 
    } 
    } 




     class Ball{ 
    int x=0; 
    int xs=-1,ys=-1; 
    int y=0; 
    JPanel jpn; 
    Ball(JPanel jpn){ 
     this.jpn=jpn; 
    } 

    public void move() { 


     if(x+xs<0){ 
      xs=1; 
     } 
     else if(y+ys<0){ 
      ys=1; 
     } 
     else if(x+xs>jpn.getWidth()-30){ 
      xs=-1; 
     } 
     else if(y+ys>jpn.getHeight()-30){ 
      ys=-1; 
     } 
     x=x+xs; 
     y=y+ys; 

    } 
    public void paint(Graphics g) { 

     jpn.setBackground(Color.black); 
     g.setColor(Color.blue); 
     g.fillOval(x, y, 50, 50); 

    } 
} 
} 
+0

由於一個線程,單球不能運行。我不明白你爲什麼創造Ball1。此外,線程的標題令人難以置信的誤導:) –

+0

爲什麼你有三個Jpanel和四個線程? –

+0

更好地分離JPanel和Runnables,讓程序的每個部分對所有其他部分的暴露程度最低,否則很快就無法看到自己的代碼。只需將Balls/JPanel作爲Runnables的參數即可。 – Trilarion

回答

1
  1. 這不需要多線程 - 我不知道你爲什麼要添加這種複雜
  2. 如果線程是用正確的事(但他們都沒有),使自己的Jpanel類是Runnable是不正確的做法。你想要做的是使Ball類可以運行,並且以與屏幕上繪製東西完全分離的方式更新其位置。混合渲染和移動不是一個很好的分離問題。只需讓球擔心它在哪裏以及它在哪裏移動,並讓UI擔心繪製它的位置。
  3. Swing調度時可以重新繪製它,所以你一定會發現,在某些時候,重繪事件的請求不會總是以一致的幀速率發生,這可能不是你期望的或實際的需要。
  4. 如果有機會嘗試製作遊戲,Swing is going to be a massive waste of your time。你需要的是更直接的屏幕渲染。用Swing構建遊戲會慢慢地殺死你的精神並讓你想哭。改爲使用類似Slick2Dlibgdx的東西。
  5. 您在自定義Jpanel類中聲明的Thread實例甚至未被使用。
  6. 通話Thread.sleep(1)是毫無意義的。爲什麼如果你在屏幕上畫球並且你只在球運動之間等待大約1毫秒就睡不着?如果你不使用多線程,你可以睡一段合理的時間(比如大約1/60秒),或者你可以隨時全速運行。
+0

他沒有直接在組件上調用'paint(...)'。他將其稱爲邏輯(非GUI)類Ball1的對象,該類不擴展任何Swing或AWT組件,因此他的代碼在這方面是可以的。他仍然應該覆寫paintComponent而不是繪畫。我也不確定你的第二點。 –

+0

有人編輯了OP的帖子。最初沒有要求重新繪製的電話。最初,在'Ball'類中,OP在'JPanel'實例變量上調用'.paint'。 – jefflunt

+0

我最初發布時複製了他的代碼,並且重繪調用都在那裏,所以我不同意,但不管怎樣,直接調用「paint(...)」都是因爲它們位於Ball1對象上。 Swing也在同一個線程中做繪畫和用戶交互。 **編輯**我剛通過他原始文章的編輯歷史記錄時,我確認'repaint()'調用總是在那裏。 –