2010-01-19 54 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