[英]How do I speed up this swing animation?
我正在將動畫繪制到秋千JPanel上。 1024x1024屏幕分為2000個,完全覆蓋屏幕(無重疊)。
每塊都是屏幕的很小一部分(1/2000)。 通過更改緩沖圖像中的像素並調用reaint(),動畫每毫秒繪制一張圖片。 因此,整個屏幕每2秒更改一次。 動畫在java.util.Timer任務中運行。
緩沖的圖像不會被加速並且不會揮發。 我將其優先級設置為1。
框架根窗格已優化。 前緩沖區和后緩沖區都被加速,但不是不穩定的。
這樣就可以了。
分析表明,幾乎所有grahic時間都花在繪制緩沖的圖像上,正如人們所期望的那樣。使用一些臟矩形似乎並沒有幫助減少繪制時間。
如果我用正確的形狀裁剪緩沖圖像的圖形,則該部分將被繪制,並且屏幕的其余部分變為白色。
我想要的是讓屏幕的其余部分保持原樣,並且只繪制剪切的形狀。
為每一塊制作像素需要混合10層,因此需要進行一些計算。 可以/應該在awt計時器線程中做得更好嗎?
還是應該使用畫布和更新技巧http://java.sun.com/products/jfc/tsc/articles/painting/src/UpdateDemo.java
我已經看到包含Toolkit.getDefaultToolkit()。setDynamicLayout(true);的建議; System.setProperty(“ sun.awt.noerasebackground”,“ true”);
其他建議包括立即繪畫,以及將JComponent而不是JPanel子類化。
我覺得這一切令人困惑。
我希望此操作系統盡可能獨立,但該應用程序將主要在Windows 7上運行。
我要在這里采取的下一個(小的)邏輯步驟是什么?
更新:使用畫布(無更新技巧)可顯着減少繪制緩沖圖像所花費的時間。 而不是放在探查器的最上面,我找不到它! 使用面板時,我可能做的比我應該做的要多。
這里有一些建議:
嚴格檢查是否需要每毫秒repaint()
; 特別是,看是否可以合並某些更新。
考慮一下java.swing.Timer
的便利性,它在EDT上呈現並支持合並事件。
如不需要AnimationTest
所示,對drawImage()
調用最快。
始終盡可能地預先計算圖像,如此KineticModel
中建議的那樣,該KineticModel
說明了幾種動畫技術。
KineticModel
使用的TexturePaint
也顯示在此處 。
此處說明的IndexColorModel
可能適用。
編輯更好的例子
本質上,我們可以使用RepaintManager
來跟蹤/更新每毫秒更改的幾個像素。 臟區域將累積,直到真正能夠發生油漆為止。 當繪制發生時,它使用paintImmediately(int x, int y, int w, int h)
函數(除非整個組件都是臟的)-因此,我們僅需更新圖像的一小部分即可。 希望示例代碼不依賴於操作系統-讓我知道它是否對您不起作用。
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class UpdatePane extends JPanel{
final int MAX = 1024;
//The repaint manager in charge of determining dirty pixels
RepaintManager paintManager = RepaintManager.currentManager(this);
//Master image
BufferedImage img = new BufferedImage(MAX, MAX, BufferedImage.TYPE_INT_RGB);
@Override
public void paintComponent(Graphics g){
g.drawImage(img, 0, 0, null);
}
public void paintImmediately(int x, int y, int w, int h){
BufferedImage img2 = img.getSubimage(x, y, w, h);
getGraphics().drawImage(img2, x, y, null);
}
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
final UpdatePane outside = new UpdatePane();
outside.setPreferredSize(new Dimension(1024,1024));
JFrame frame = new JFrame();
frame.add(outside);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
outside.new Worker().execute();
}
});
}
//Goes through updating pixels (like your application would)
public class Worker extends SwingWorker<Integer, Integer>{
int currentColor = Color.black.getRGB();
public int x = 0;
public int y = 0;
@Override
protected Integer doInBackground() throws Exception {
while(true){
if(x < MAX-1){
x++;
} else if(x >= MAX-1 && y < MAX-1){
y++;
x = 0;
} else{
y = 0;
x = 0;
}
if(currentColor < 256){
currentColor++;
} else{
currentColor = 0;
}
img.setRGB(x, y, currentColor);
//Tells which portion needs to be repainted [will call paintImmediately(int x, int y, int w, int h)]
paintManager.addDirtyRegion(UpdatePane.this, x, y, 1, 1);
Thread.sleep(1);
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.