我在一个摇摆的JPanel上画动画。 1024x1024屏幕分为2000个部分,完全覆盖屏幕(不重叠)。
每一块都是屏幕的一小部分(1/2000')。动画通过更改缓冲图像中的像素并调用reaint(),每毫秒绘制一个片段。所以在整个屏幕上每2秒更换一次。动画在java.util.Timer任务中运行。
缓冲图像未加速且不易变。我将它的优先级设置为1。
优化框架根窗格。正面和背面缓冲都是加速但不易变的。
这没问题。
分析表明,几乎所有的grahics时间都是按照人们的预期绘制缓冲图像,使用一些脏矩形似乎无助于缩短绘制时间。
如果我使用精确的形状剪切缓冲图像的图形,那么该图块会被绘制,而屏幕的其余部分会变为白色。
我想要的是让屏幕的其余部分保持原样,只是让剪裁的形状被绘制。
制作每个像素的像素需要混合10个图层,因此在那里进行了一些计算。 可以/应该在awt计时器线程中做得更好吗?
或者我应该使用画布和更新技巧http://java.sun.com/products/jfc/tsc/articles/painting/src/UpdateDemo.java
我见过包含Toolkit.getDefaultToolkit()的建议.setDynamicLayout(true); System.setProperty( “sun.awt.noerasebackground”, “真”);
其他建议包括paintimmedialtely,并继承JComponent而不是JPanel。
我发现这有点令人困惑。
我希望尽可能保持这个操作系统独立,但该应用程序将主要在Windows 7上运行。
我在这里采取的下一个(小)逻辑步骤是什么?
更新:使用画布(没有更新技巧)显着减少了绘制缓冲图像所花费的时间。而不是这个在探查器的顶线,我找不到它!当我使用面板时,我可能会比我应该做的更多。
答案 0 :(得分:3)
以下是一些建议:
严格审查每毫秒repaint()
的需要;特别是,看看是否可以合并某些更新。
考虑java.swing.Timer
的便利性,它在EDT上呈现并支持合并事件。
如果不需要缩放,则drawImage()
的呼叫速度最快,如AnimationTest
所示。
始终按照本KineticModel
中的建议尽可能预先计算图像,以说明几种动画技术。
TexturePaint
中使用的 KineticModel
也会显示here。
IndexColorModel
,图示为here,可能适用。
sscce将允许您隔离各种方法以便于分析。
答案 1 :(得分:2)
编辑更好的例子
基本上我们可以使用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);
}
}
}
}