2013-03-26 79 views
1

我有一個乒乓球(種)的項目,它的工作原理,但有run()函數中的問題。如果我用寫給面板的功能(他們工作,我檢查)繪製框架,它會給圖形帶來問題,如果我使用重繪(如我suupose)繪製框架並立即刪除它,每個解決方案都會幫助(在我的代碼的水平更好的一個簡單的一個):repaint - 繪畫和立即刪除

import java.awt.*; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JPanel; 
import java.util.Random; 
import javax.swing.*; 
import sun.org.mozilla.javascript.internal.Kit; 



public class Picture extends JPanel implements MouseListener, Runnable{ 

    private int k = 0; 
    Thread MyThread; 
    private DrawPic img; 

    private Rectangle r1, r3; 

    public Picture(DrawPic img, Rectangle rect1, Rectangle rect3) { 
     super(); 
     this.setLocation(0, 85); 
     this.setLayout(new FlowLayout()); 
     this.setSize(1280, 1024); 

     this.addMouseListener(this); 
     this.setFocusable(true); 

     this.r1 = rect1; 

     this.r3 = rect3; 
     this.img = img; 
     this.MyThread = new Thread(this); 
     MyThread.start(); 
     this.setVisible(true); 

    } 




    public void paintRectangleL(Rectangle rect, Graphics g) { 
     k = 3; 

     rect.DrawRectangle(g); 
     rect.FillRectangle(g); 


    } 
    public void paintRectangleR(Rectangle rect, Graphics g) { 
     k = 1; 

     rect.DrawRectangle(g); 
     rect.FillRectangle(g); 

    } 
    public void paintImage(DrawPic img, Graphics g) { 
     k = 2; 

     //g.clearRect(0, 0, this.getWidth(), this.getHeight()); 
     img.DrawImg(g, this); 



    } 
    public void changeK(int k1){ 
     k = k1; 
    } 

    @Override 
    public void mouseClicked(MouseEvent e) { 
     // throw new UnsupportedOperationException("Not supported yet."); 



    } 

    @Override 
    public void mousePressed(MouseEvent e) { 
     //throw new UnsupportedOperationException("Not supported yet."); 

      Point p = r3.FindCenter(); 
      double dx, dy; 

      dy = e.getY() - p.getY(); 
      r3.Move(0, dy); 
       this.getGraphics().clearRect(0, 0, this.getWidth(), this.getHeight()); 
      this.paintRectangleL(r3, this.getGraphics()); 
      this.paintRectangleR(r1, this.getGraphics()); 
      this.paintImage(img, this.getGraphics()); 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 
     //throw new UnsupportedOperationException("Not supported yet."); 

    } 

    @Override 
    public void mouseEntered(MouseEvent e) { 
     //throw new UnsupportedOperationException("Not supported yet."); 
    } 

    @Override 
    public void mouseExited(MouseEvent e) { 
     // throw new UnsupportedOperationException("Not supported yet."); 
    } 
    public void animate(){ 
     double dx = 0, dy = 2; 
     if ((this.img.getX() + 160 + this.r1.RightPoint().getX() - this.r1.LeftPoint().getX() > this.getWidth() || this.img.getX() < this.r3.RightPoint().getX() - this.r3.LeftPoint().getX())) { 
        dx = -1 * dx; 


       } 
       if (this.img.getY() + 120> this.getHeight() || this.img.getY() < 0) { 
        dy = -1 * dy; 
       } 
       img.Move(dx, dy); 
      // this.getGraphics().clearRect(0, 0, this.getWidth(), this.getHeight()); 
       // this.paintImage(img, this.getGraphics()); 
       // this.paintRectangleL(r3, this.getGraphics()); 
       // this.paintRectangleR(r1, this.getGraphics()); 
       repaint();    
    } 

    @Override 
    public void run() { 

     Color col; 
     while (true) { 
       animate(); 

       try { 
        MyThread.sleep(35); 
       } catch (InterruptedException ex) { 
        Logger.getLogger(Picture.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      } 
     } 
     // throw new UnsupportedOperationException("Not supported yet."); 
    } 
+1

你可能會想要重載'paintComponent()'並在那裏添加你所有的繪畫。 'paintComponent'將有一個Graphics參數,你可以使用它(而不必調用'getGraphics()'),並且會從'repaint()'中自動調用。 – SeKa 2013-03-26 22:15:19

回答

5

你不應該使用getGraphics()的風俗畫,因爲它是下次上重繪回收臨時緩衝區。你畫在paintComponent()

有關更多信息和示例,請參閱Performing Custom Painting。部分A Closer Look at the Paint Mechanism有一個很好的總結paint()paintComponent()方法。另見Painting in AWT and Swing

編輯:

的邏輯和程序不符合Swing的繪製過程的結構。您需要重構您的程序,以便它能夠在適當的時候插入該過程並繪製正確的內容。 通常,您可以通過覆蓋其paintComponent()來自定義組件。在那種方法中,所有的繪畫都會發生此方法應儘可能快,避免在其中放置太多/太多的應用程序邏輯。

一旦狀態更改問題repaint(),您應該保持某種狀態的繪製對象(即座標,顏色等)。這將安排重新繪製,並且最終Swing將在將調用paintComponent()的組件上執行paint()

在你的情況下,你有一個定期觸發的計時器。您可以覆蓋您使用的JPanelpaintComponent。你已經有了計算座標的邏輯。將這些座標存儲在成員變量中。然後,問題repaint()。在paintComponent中,根據計算出的座標繪製圖像。

編輯:

上線另一個需要注意的。 Swing有一個單線程繪製模型。所有UI交互和繪畫都在Swing的Event Dispatch Thread(EDT)上進行。查看Concurrency in Swing獲取更多關於EDT的信息。請注意,方法animate()未在EDT上執行。您沒有顯示img.Move(dx, dy)的功能,但以這種方式執行可能不安全。 invokeLater可能有助於確保代碼在EDT上執行。但是,在這種特殊情況下,使用Swing timers可能會更容易,這確保了操作在EDT上進行。

+0

例如,請參閱[this](http://stackoverflow.com/a/12336475/1048330)示例,它在定時器脈衝上移動圖像。 – tenorsax 2013-03-26 23:34:51

+0

對於java的無知感到抱歉,但是您能否給予更清楚的東西? – TJR 2013-03-26 23:57:43

+0

@ user2213455請參閱編輯,另請參閱鏈接的示例。 – tenorsax 2013-03-27 00:26:49