2015-04-28 72 views
1

我知道在鞦韆中你打算使用重繪重畫一個面板,但我開始製作遊戲並且已經讀過重繪在時間上不可靠。所以我試圖制定一個策略,在其中創建一個BufferedImage,將所需的每件東西繪製到該對象圖形對象,然後使用drawImage方法將圖像繪製到我的jpanel中。爲什麼我的繪圖方法只能在某些時間運行?

我打電話處置讓面板重新渲染,但它只在某些時間工作。以下只是一個例子。如果你繼續運行這個程序,那麼BufferedImage只能運行〜3/10次。有人可以向我解釋這個嗎?

public class TestMain { 

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

    JFrame jf = new JFrame(); 
    MyPanel mp = new MyPanel(); 
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    jf.setLocation(50, 500); 
    jf.add(mp); 
    jf.pack(); 
    jf.setVisible(true); 

    mp.draw(); 
} 
} 

public class MyPanel extends JPanel { 

private static final long serialVersionUID = 1L; 

BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); 
Graphics2D g2d; 

public MyPanel() { 
    super(); 
    setPreferredSize(new Dimension(300, 300)); 
} 

public void draw() { 
    System.out.println("In draw"); 
    g2d = (Graphics2D) img.getGraphics(); 
    g2d.drawString("Test", 10, 10); 

    Graphics g = getGraphics(); 

    g.drawImage(img, 0, 0, this); 
    g.dispose(); 
} 

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    System.out.println("In paintComponent"); 
} 

} 

什麼是我在這裏與經常阻斷平局的幕後作戰?我意識到調整窗口大小等將調用重繪並覆蓋我的繪圖,但是當我不這樣做時,它應該每次都顯示,不是嗎?

編輯:有趣......如果我在連續的while循環中包裝繪製方法,它「起作用」。但是這並不能回答我的問題。我不應該不斷地回想一下這種方法來給人一種錯覺,認爲它很好。

+0

之前'jf.setVisible(真);'嘗試加入'jf.revalidate(); jf.repaint();' – MaVRoSCy

+0

@MaVRoSCy都能跟得上。同樣的結果。每隔幾次運行一次。 –

+0

顯示框架後調用'draw()'方法。 (在WindowOpened操作中,我建議..) –

回答

1

您不應該使用getGraphics()方法進行繪畫。任何使用getGraphics的代碼都是臨時的,只要Swing確定組件需要重新繪製,這可能就是在這裏發生的。

覆蓋類的getPreferredSize()方法並調用super.paintComponent(),然後添加System.out.println(...)語句。另外,在draw()方法中添加一個System.out.println(...)語句來查看代碼的執行順序。

我打電話處置訪問面板重新渲染,

不會導致面板來渲染,它只是將釋放分配給顯卡的資源對象。您需要調用draw()方法來持續重繪。

這與使用計時器來持續重繪()組件相同。不同之處在於draw()可能會立即發生,但重繪可能需要幾毫秒。但是由於repaint()每次間隔將保持不變,因此repaint()會花費幾ms,它不會像repaint一樣繪製一次,然後等待下一次。

+0

嗨,我引用了「Java中的殺手遊戲編程」這本書,它鼓勵使用getGraphics繪製,而不是依賴重繪和重載paintComponent().... 「調用repaint ();它的功能 已被合併到paintScreen()中 活動渲染將渲染緩衝圖像的任務放到屏幕上我的手 這意味着渲染時間可以被準確地測量,並且關於重繪請求被延遲或由JVM消失而關注 「 –

+0

另外,你是正確的,處置只釋放資源。 –

+0

您詢問了我提供的問題的解釋。您是否通過添加System.out.println(...)語句來驗證結果? – camickr

1

我固定的代碼,並得到如下界面:

enter image description here

當你畫一個緩衝的圖像上,你所要做的一切。您必須繪製背景並繪製前景。

當您在JPanel的paintComponent方法中繪製緩衝圖像時,您只需繪製圖像。

Swing paintComponent方法在Java版本6,7和8中足夠快以進行繪製而不閃爍。我已經完成了成千上萬行不閃爍的動畫。

您必須通過調用SwingUtilities invokeLater方法在Event Dispatch線程上啓動Swing應用程序。

這是您的修改代碼。

package com.ggl.testing; 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.image.BufferedImage; 

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

public class TestMain implements Runnable { 

    @Override 
    public void run() { 
     JFrame jf = new JFrame(); 
     MyPanel mp = new MyPanel(); 
     jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     jf.setLocation(50, 50); 
     jf.add(mp); 
     jf.pack(); 
     jf.setVisible(true); 
     mp.draw(); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new TestMain()); 
    } 

    public class MyPanel extends JPanel { 

     private static final long serialVersionUID = 1L; 

     BufferedImage img = new BufferedImage(100, 100, 
       BufferedImage.TYPE_INT_RGB); 
     Graphics2D g2d; 

     public MyPanel() { 
      super(); 
      setPreferredSize(new Dimension(300, 300)); 
     } 

     public void draw() { 
      System.out.println("In draw"); 
      g2d = (Graphics2D) img.getGraphics(); 
      g2d.setColor(Color.WHITE); 
      g2d.fillRect(0, 0, img.getWidth(), img.getHeight()); 
      g2d.setColor(Color.BLACK); 
      g2d.drawString("Test", 30, 50); 
      g2d.dispose(); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      System.out.println("In paintComponent"); 
      g.drawImage(img, 0, 0, this); 
     } 

    } 

} 
+0

嗨吉爾伯特。當時,我完全忽略了在EDT上運行該程序!謝謝。 「Swing paintComponent方法在Java版本6,7和8中速度足夠快,可以不閃爍地進行繪製。我已經完成了數萬行不閃爍的動畫。」 - 這是很好的知道,因爲我已經讀到它不夠好。 –

+0

@AlanSmith,「我完全忽略了在EDT上運行這個程序!」我在我的評論中提到了這個,並給了你Swing教程的鏈接。這個答案仍然沒有解釋隨機行爲,它只表現出正常的Swing繪畫。由於RepaintManager整合了repaint()請求並將請求添加回EDT,因此您仍然可能遇到計時問題。因此,如果您的遊戲處理大量KeyEvent,則理論上可以減緩重繪週期。我認爲這是本書正在討論的時間問題類型。 – camickr

相關問題