2015-03-03 130 views
0

我正在繪製使用paintComponent()定義的車輛對象。 由於車輛可以移動,我實現了ActionListener並設置了一個Timer()來觸發。repaint()的繪製速度比paintComponent()慢嗎?

因此,我的車輛可以移動。但它有點「動搖」。當我不斷調整窗口大小來調用paintComponent()時,運動變得平滑。當我不調整窗口大小(不調用paintComponent)時,它會再次出現黑屏。爲什麼?如何解決它?

public class VehiclesComponent extends JComponent implements ActionListener{ 
    private Vehicle[] vehicles; 
    private Timer timer; 

    public VehiclesComponent(int n){ 
     vehicles = Vehicle.generateVehicle(n); 
     timer = new Timer(5,this); 
    } 

    public void paintComponent(Graphics g){ 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D)g; 

     for (int i=0; i<vehicles.length; i++) { 
      vehicles[i].draw(g2); 
     } 

     // may change later 
     timer.start(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e){ 

     //check collision in here 
     for (Vehicle v : vehicles) { 
      if (Vehicle.intersectsOther(v, vehicles)) { 
       v.collisionSideEffect(); 
      } 
     } 

     //move all in here 

     for (Vehicle v : vehicles) { 
      v.move(); 
     } 

     repaint(); 
     //?? repaint slower than paintComponent 
    } 


} 
+0

'公共無效paintComponent(圖形克){..'作爲圍繞提到這裏**在日常基礎上,**應該是'public void paintComponent(Graphics g){super.paintComponent(g); ..'並且1)移動'//可能稍後改變 timer.start();'在我們不控制它的時間和次數的方法之外。 2)使用合乎邏輯的一致形式縮進代碼行和塊。縮進旨在使代碼的流程更易於遵循! – 2015-03-03 05:55:45

+0

它應該保持'受保護' – MadProgrammer 2015-03-03 05:56:14

+0

首先看看[在AWT和Swing中繪畫](http://www.oracle.com/technetwork/java/painting-140037.html)'。 'repaint'向負責安排Event Queue上的繪畫事件的'RepaintManager'發出一個請求。爲了提高性能,可以將「重繪」請求合併到單個(或更少數量)的繪畫事件中。 – MadProgrammer 2015-03-03 05:57:46

回答

1

首先看看Painting in AWT and Swing。請記住,repaint只是對RepaintManager的建議,RepaintManager可能會選擇將多個repaint調用合併爲較少數量的實際繪畫事件。

確保你打電話給super.paintComponent,否則你將最終沒有奇怪的油漆文物結束。

不要,直接或間接地修改組件或從任何油漆方法內螞蟻其它組件的狀態,這將導致一個新repaint請求而做出的,這可能導致油漆事件的循環可能消耗你的CPU週期。這意味着,請不要撥打timer.start()

沒有一個可運行的例子,我一起蹣跚而行。現在,這是動畫10,000個人Vehicle S(矩形),所以它在大量殺死,但它應該提供的點...

Noise

(GIF將只在運行7FPS,而不是你200fps)

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.Shape; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new VehiclesComponent(10000)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class VehiclesComponent extends JComponent implements ActionListener { 

     private Vehicle[] vehicles; 
     private Timer timer; 

     public VehiclesComponent(int n) { 
      vehicles = Vehicle.generateVehicle(n, getPreferredSize()); 
      timer = new Timer(5, this); 

      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(400, 400); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2 = (Graphics2D) g; 

      for (int i = 0; i < vehicles.length; i++) { 
       vehicles[i].draw(g2); 
      } 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 

      //check collision in here 
//   for (Vehicle v : vehicles) { 
//    if (Vehicle.intersectsOther(v, vehicles)) { 
//     v.collisionSideEffect(); 
//    } 
//   } 

     //move all in here 
      for (Vehicle v : vehicles) { 
       v.move(this.getSize()); 
      } 

      repaint(); 
      //?? repaint slower than paintComponent 
     } 

    } 

    public static class Vehicle { 

     protected static final int SIZE = 5; 
     protected static final Color[] COLORS = new Color[]{ 
      Color.BLACK, 
      Color.BLUE, 
      Color.CYAN, 
      Color.DARK_GRAY, 
      Color.GREEN, 
      Color.MAGENTA, 
      Color.ORANGE, 
      Color.PINK, 
      Color.RED, 
      Color.WHITE, 
      Color.YELLOW 
     }; 

     private int x = 0; 
     private int y = 0; 

     private int xDelta; 
     private int yDelta; 

     private Shape car; 
     private Color color; 

     public static Vehicle[] generateVehicle(int count, Dimension bounds) { 

      Vehicle[] vehicles = new Vehicle[count]; 
      for (int index = 0; index < vehicles.length; index++) { 
       vehicles[index] = new Vehicle(bounds); 
      } 

      return vehicles; 

     } 

     public Vehicle(Dimension size) { 

      x = (int)(Math.random() * (size.width - SIZE)); 
      y = (int)(Math.random() * (size.height - SIZE)); 

      xDelta = (int)(Math.random() * 3) + 1; 
      yDelta = (int)(Math.random() * 3) + 1; 
      car = new Rectangle(SIZE, SIZE); 

      color = COLORS[(int)(Math.random() * COLORS.length)]; 

     } 

     public void move(Dimension size) { 
      x += xDelta; 
      y += yDelta; 

      if (x < 0) { 
       x = 0; 
       xDelta *= -1; 
      } else if (x + SIZE > size.width) { 
       x = size.width - SIZE; 
       xDelta *= -1; 
      } 
      if (y < 0) { 
       y = 0; 
       yDelta *= -1; 
      } else if (y + SIZE > size.height) { 
       y = size.height - SIZE; 
       yDelta *= -1; 
      } 

     } 

     public void draw(Graphics2D g2) { 
      g2.translate(x, y); 
      g2.setColor(color); 
      g2.fill(car); 
      g2.translate(-x, -y); 
     } 

    } 

} 

你也可以看看this example這使得在任意方向4500幅圖像的向上和演示了一些優化技術。

也可以看看this example,其能夠在兩個方向和旋轉動畫的,向上的10,000圖像

+0

*「所以它是大量殺死」*沒有殺死像過度殺傷。 :) – 2015-03-03 06:58:57

+0

雖然我看到只對現有代碼進行「少量」修改(爲了提供*答案*,而不僅僅告訴提問者他正在使用錯誤的方法),應該強調的是* *不應該濫用「組件」作爲精靈**。一個組件是一個組件,一個精靈是一個精靈。繪製10000個簡單的矩形(在一個自己的組件中,在'paintComponent' metehod)將有可能遠遠超過7 fps ... – Marco13 2015-03-03 09:28:48

+0

@ Marco13前兩點是,調用'super.paintComponent',不要調用'paintComponent'方法中的'timer.start'。 gif動畫是7fps,因此它看起來有點「交錯」的原因,這個例子能夠達到200fps。前兩點將根據OP提供的內容而有所不同。 OP沒有提供任何關於他們繪畫或如何的信息,因此不可能提供更多細節。如果你喜歡我可以發佈一個鏈接到一個動畫4000-5000隨機圖像的例子...... – MadProgrammer 2015-03-03 09:57:20