虽然这是一篇旧文章,但我想分享一下关于使用Swing/AWT进行直接绘制而不使用BufferedImage的发现。
某些类型的绘图,例如3D,最好直接绘制到一个int[]缓冲区中。完成图像后,可以使用一个ImageProducer实例(如MemoryImageSource)来生成图像。我假设您知道如何直接进行绘图,而无需使用Graphics/Graphics2的帮助。
public class MyCanvas extends JPanel implements Runnable {
public int pixel[];
public int width;
public int height;
private Image imageBuffer;
private MemoryImageSource mImageProducer;
private ColorModel cm;
private Thread thread;
public MyCanvas() {
super(true);
thread = new Thread(this, "MyCanvas Thread");
}
public void init(){
cm = getCompatibleColorModel();
width = getWidth();
height = getHeight();
int screenSize = width * height;
if(pixel == null || pixel.length < screenSize){
pixel = new int[screenSize];
}
mImageProducer = new MemoryImageSource(width, height, cm, pixel,0, width);
mImageProducer.setAnimated(true);
mImageProducer.setFullBufferUpdates(true);
imageBuffer = Toolkit.getDefaultToolkit().createImage(mImageProducer);
if(thread.isInterrupted() || !thread.isAlive()){
thread.start();
}
}
public void render(){
int[] p = pixel;
if(p.length != width * height) return;
for(int x=0; x < width; x++){
for(int y=0; y<height; y++){
int color = (((x + i) % 255) & 0xFF) << 16;
color |= (((y + j) % 255) & 0xFF) << 8;
color |= (((y/2 + x/2 - j) % 255) & 0xFF) ;
p[ x + y * width] = color;
}
}
i += 1;
j += 1;
}
private int i=1,j=256;
@Override
public void run() {
while (true) {
repaint();
try {Thread.sleep(5);} catch (InterruptedException e) {}
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
render();
mImageProducer.newPixels();
g.drawImage(this.imageBuffer, 0, 0, this);
}
@Override
public boolean imageUpdate(Image image, int a, int b, int c, int d, int e) {
return true;
}
}
请注意,我们需要唯一的
MemoryImageSource和
Image实例。除非您已调整JPanel的大小,否则不要为每个帧创建新的Image或新的ImageProducer。请参见上面的
init()方法。
在渲染线程中,请求
repaint()。在Swing上,
repaint()将调用重写的
paintComponent(),其中它调用您的
render()方法,然后要求您的imageProducer更新图像。完成Image后,使用
Graphics.drawImage()绘制它。
为了拥有兼容的Image,请在创建Image时使用适当的
ColorModel。我使用
GraphicsConfiguration.getColorModel():
protected static ColorModel getCompatibleColorModel(){
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
return gfx_config.getColorModel();
}