我正在使用循环来调用双缓冲绘画。这与覆盖我唯一的Panel重绘方法一起,旨在将重绘的完全控制传递给我的循环,并且仅在必要时进行渲染(即在GUI中进行了一些更改)。
这是我的渲染例程:
Log.write("renderer painting");
setNeedsRendering(false);
Graphics g = frame.getBufferStrategy().getDrawGraphics();
g.setFont(font);
g.setColor(Color.BLACK);
g.fillRect(0, 0, window.getWidth(),window.getHeight());
if(frame != null)
window.paint(g);
g.dispose();
frame.getBufferStrategy().show();
正如您所看到的,它非常标准。我从缓冲区策略中获取了grpahics对象(初始化为2),将其全部变为黑色并将其传递给我的“window”对象的paint方法。
使用图形对象完成窗口后,我将其处理并在缓冲区策略上调用show以显示虚拟缓冲区的内容。
重要的是要注意窗口将图形对象传递给填充窗口的许多其他子组件,然后每个组件使用相同的图形对象实例在屏幕上绘制内容:文本,形状或图像。
我的问题开始显示系统何时运行并呈现大图像。图像看起来被切割成半成品并一次又一次地(3-4次)绘制,在图像应该被渲染的地方内部具有不同的偏移。请参阅我附带的图片:
这是原始图片: alt text http://img109.imageshack.us/img109/8308/controller.png
这就是我得到的: alt text http://img258.imageshack.us/img258/3248/probv.png
请注意,在第二张图片中,我在图片上渲染形状 - 这些形状总是在正确的位置。
知道为什么会这样吗? 如果我将图像保存到文件中,就像它在内存中一样,就在调用g.drawImage(...)之前,它与原始图像相同。
答案 0 :(得分:2)
setIgnoreRepaint(假);
关闭Swing渲染,设置绘图循环并绘制内容本身。 或者您可以使用JOGL进行OpenGL渲染。您正在使用的方法似乎完全正确 与正确的Java2D使用不一致。
这里正确使用:
public final class FastDraw extends JFrame {
private static final transient double NANO = 1.0e-9;
private BufferStrategy bs;
private BufferedImage frontImg;
private BufferedImage backImg;
private int PIC_WIDTH,
PIC_HEIGHT;
private Timer timer;
public FastDraw() {
timer = new Timer(true);
JMenu menu = new JMenu("Dummy");
menu.add(new JMenuItem("Display me !"));
menu.add(new JMenuItem("Display me, too !"));
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
setJMenuBar(menuBar);
setIgnoreRepaint(true);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
super.windowClosing(evt);
timer.cancel();
dispose();
System.exit(0);
}
});
try {
backImg = javax.imageio.ImageIO.read(new File("MyView"));
frontImg = javax.imageio.ImageIO.read(new File("MyView"));
}
catch (IOException e) {
System.out.println(e.getMessage());
}
PIC_WIDTH = backImg.getWidth();
PIC_HEIGHT = backImg.getHeight();
setSize(PIC_WIDTH, PIC_HEIGHT);
createBufferStrategy(1); // Double buffering
bs = getBufferStrategy();
timer.schedule(new Drawer(),0,20);
}
public static void main(String[] args) {
new FastDraw();
}
private class Drawer extends TimerTask {
private VolatileImage img;
private int count = 0;
private double time = 0;
public void run() {
long begin = System.nanoTime();
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
GraphicsConfiguration gc = g.getDeviceConfiguration();
if (img == null)
img = gc.createCompatibleVolatileImage(PIC_WIDTH, PIC_HEIGHT);
Graphics2D g2 = img.createGraphics();
// Zeichenschleife
do {
int valStatus = img.validate(gc);
if (valStatus == VolatileImage.IMAGE_OK)
g2.drawImage(backImg,0,0,null);
else {
g.drawImage(frontImg, 0, 0, null);
}
// volatile image is ready
g.drawImage(img,0,50,null);
bs.show();
} while (img.contentsLost());
time = NANO*(System.nanoTime()-begin);
count++;
if (count % 100 == 0)
System.out.println(1.0/time);
}
}