[英]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.