2010-01-19 83 views
0

我正在使用循环调用双缓冲绘画。这与重写我的唯一Panel的重绘方法一起,旨在将重绘的完全控制权传递给我的循环,并仅在必要时渲染(即在GUI中进行了一些更改)。Java - 使用Graphics.drawImage()和双屏缓冲策略绘制多个图像扭曲并剪切图像

这是我的渲染程序:

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),将其全部设为黑色并将其传递给我的“窗口”对象的绘制方法。

使用图形对象完成窗口后,我将其弃置并在缓冲区策略上调用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(...)之前,它与原始图像相同。

回答

2

呃,你在使用Swing吗?
正常挥杆自动呈现图像,您不能将其关闭。重绘() 方法超出范围,因为Swing由于 方法兼容性AWT小部件和若干优化,包括必要时仅绘制 必要时由于非常复杂的呈现例程! 如果你想使用高速绘图API,你可以使用一个component,其BufferStrategy中 喜欢的JFrame和窗口,使用

setIgnoreRepaint(假);

关闭摆动渲染,设置绘制循环并绘制内容本身。 或者您可以使用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); 
    } 
    } 
+0

感谢您的答复。 我不明白你检查易失形象的状态的部分。如果没问题,你可以画g2,但如果不画,你画g?为什么? 我猜这个frontImg和backImg是你用来调试这个代码的两个不同的图像? 此外,为什么在易失性图像的内容丢失的时候,你会一遍又一遍地重复绘图? – Warlax 2010-01-22 22:15:37

+0

即使我实施了您的建议,问题仍然存在。 – Warlax 2010-01-22 22:28:24