2013-03-26 72 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