2014-09-02 39 views
0

我有一個簡單的程序,繪製從原點以特定速度和角度發射的粒子的軌跡。我創建了一個JPanel的子類來處理這個圖。每次我的子類都重新繪製,它會以當前時間和初始時間之差(以毫秒爲單位),將其轉換爲秒,然後找到粒子應該在那個時間點的x和y座標,最後採用這些x和y座標並在屏幕上繪製它們。我的問題是,我的子類似乎在間隔時間似乎很長,因爲只顯示幾個點。如何提高JPanel的重繪頻率?

我的繪製方法:

private void doDrawing(Graphics g) { 

    Dimension size = getSize(); 
    Insets insets = getInsets(); 
    int w = size.width - insets.left - insets.right; 
    int h = size.height - insets.top - insets.bottom; 

    Graphics2D g2d = (Graphics2D) g; 
    g.drawString("Acceleration: -9.8m/s i", 0, 20); 
    StringBuilder b = new StringBuilder(); 
    b.append("Current Velocity: "); 
    b.append(String.valueOf(sim.getVector(tickSpeed 
      * ((System.currentTimeMillis() - initTime)/1000)).getMagnitude())); 
    b.append(" m/s at "); 
    b.append(String.valueOf(sim.getVector(tickSpeed 
      * ((System.currentTimeMillis() - initTime)/1000)).getDirection().getDirectionDeg())); 
    b.append(" degrees"); 
    g.drawString(b.toString(), 0, 30); 

    drawPreviousPoints(g2d); 

    drawCurrentPointAndAppend(g2d, w, h); 

    repaint(); 

} 

private void drawCurrentPointAndAppend(Graphics2D g2d, int w, int h) { 
    g2d.setColor(Color.red); 
    double height = (length/w) * h; 
    Vector2D c = sim.getVector(tickSpeed 
      * ((System.currentTimeMillis() - initTime)/1000)); 
    double currentX = w 
      * ((sim.getX(tickSpeed 
        * ((System.currentTimeMillis() - initTime)/1000)))/length); 
    double currentY = h 
      * (1 - ((sim.getY(tickSpeed 
        * ((System.currentTimeMillis() - initTime)/1000)))/height)); 

    g2d.drawLine((int) currentX, (int) currentY, (int) currentX, 
      (int) currentY); 
    g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE, 
      BasicStroke.JOIN_MITER)); 
    g2d.drawLine((int) currentX, (int) (currentY), 
      (int) (currentX + w * (c.getX()/length)), 
      (int) (currentY + (h * -(c.getY()/height)))); 
    xList.add(currentX); 
    yList.add(currentY); 

} 

private void drawPreviousPoints(Graphics2D g2d) { 
    g2d.setColor(Color.blue); 
    g2d.setStroke(new BasicStroke(7, BasicStroke.CAP_ROUND, 
      BasicStroke.JOIN_ROUND)); 
    if (!xList.isEmpty()) { 
     for (int i = 0; i < xList.size(); i++) { 
      g2d.drawLine(xList.get(i).intValue(), yList.get(i).intValue(), 
        xList.get(i).intValue(), yList.get(i).intValue()); 
     } 
    } 

} 

tickSpeed僅僅是我使用加快或顆粒減慢的變量。它運行良好;然而,動畫看起來非常波濤洶涌。

  • 我該如何解決這個振盪格局(讓一切顯得更「流體」)
  • 我應該在哪裏調用重繪()?因爲我覺得在我的繪圖方法結束時調用它是不對的。
+1

很難診斷沒有上下文的代碼片段。考慮提供一個[可運行的示例](https://stackoverflow.com/help/mcve),它可以證明你的問題。這會減少混淆和更好的反應 – MadProgrammer 2014-09-02 00:27:56

回答

5

你不控制油漆工藝Swing-的一個重要的規則...

不要paintComponent內進行這些計算。 paintComponent是爲了描繪用戶界面的當前狀態,並且可能會隨時調用,原因很多,其中大部分都不受您的控制。

取而代之,可以考慮使用javax.swing.Timer組以定期重複(40ms爲每秒25個滴答聲)。

設置一個跟蹤粒子電流處理的模型。當計時器滴答時,計算您的粒子位置並更新它們,然後致電repaint

在您的paintComponent中,只需繪製模型的當前狀態即可。

看一看Concurrency in SwingHow to use Swing Timers更多細節

1

油漆工藝是內部處理的,所以你無法控制頻率的它的執行。 但是,您可以創建單獨的線程或定時器,以期望的頻率調用進程。使用paint方法僅在畫布上進行渲染,在其他函數中執行其他邏輯和處理。