views:

167

answers:

3

Hello there, I'm having some trouble implementing DoubleBuffer into my program. Before you faint from the wall of text, you should know that a lot of it is there just in case you need to know. The actual place where I think I'm having problems is in one method.

I've recently looked up a tutorial on the gpwiki about double buffering, and decided to try and implement the code they had into the code I have that I'm trying to implement doublebuffer in. I get the following error: "java.lang.IllegalStateException: Component must have a valid peer".

I don't know if it makes any difference if you know it or not, but the following is the code with the main method. This is just a Frame that displays the ChronosDisplay class inside it. I omitted irrelevant code with "..."

public class CDM extends JFrame
{
    public CDM(String str)
    {
        super("CD:M - "+str);
        try
        {
            ...
            ChronosDisplay theGame = new ChronosDisplay(str);
            ((Component)theGame).setFocusable(true);
            add(theGame);
        }
        catch(Exception e)
        {
            System.out.println("CDM ERROR: " +e);
        }
    }
    public static void main( String args[] )
    {
        CDM run = new CDM("DP_Mini");
    }
}

Here is the code where I think the problem resides (I think the problem is in the paint() method). This class is displayed in the CDM class

public class ChronosDisplay extends Canvas implements  Runnable
{
    String mapName;
    public ChronosDisplay (String str)
    {
        mapName = str;
        new Thread(this).start();
        setVisible(true);
        createBufferStrategy(2);
    }
    public void paint( Graphics window )
    {
        BufferStrategy b = getBufferStrategy();
        Graphics g = null; 
        window.setColor(Color.white);
        try
        {
             g = b.getDrawGraphics();
            paintMap(g);
            paintUnits(g);
            paintBullets(g);
        }
        finally
        { g.dispose(); }
        b.show();
        Toolkit.getDefaultToolkit().sync(); 
    }
    public void paintMap( Graphics window )
    {
        TowerMap m = new TowerMap();
        try
        {
            m = new TowerMap(mapName);
            for(int x=0; x<m.getRows()*50; x+=50)
            {
                for(int y = 0; y<m.getCols()*50; y+=50)
                    {
                        int tileType = m.getLocation(x/50,y/50);
                        Image img;
                        if(tileType == 0)
                        {
                            Tile0 t = new Tile0(x,y);
                            t.draw(window);
                        }
                        ...// More similar if statements for other integers
            }
            catch(Exception e) ...
    }
    ...// Additional methods not shown here
    public void run()
    {
        try
        {
            while(true)
            {
                Thread.currentThread().sleep(20);
                repaint();
            }
        }
        catch(Exception e) ...
    }
}

If you're curious (I doubt it matters), the draw() method in the Tile0 class is:

public void draw( Graphics window )
{
    window.drawImage(img,getX(),getY(),50,50,null);
}

Any pointers, tips, or solutions are greatly appreciated. Thanks for your time! :D

A: 

Usually that error in regards to double buffering means the target isn't visible yet. Try pushing the thread start to after the window is set visible and the double buffer strategy is created

Michael Mrozek
Sorry, changing the constructor method to...public ChronosDisplay (String str){ mapName = str; setVisible(true); createBufferStrategy(2); new Thread(this).start();}...doesn't solve the problem (I still get the same error).
DDP
Don't confuse visible with displayable
finnw
+2  A: 

Swing is double buffered by default so you don't need to implement it yourself.

You should not be using the Canvas class in a Swing application. That is don't mix AWT and Swing components.

All Swing components should be created on the EDT. Read the Swing tutorial for examples on on how to do this.

camickr
Thanks for pointing me in the general direction, camikr. But, could you please tell me what EDT is? A simple search on Google doesn't come up with relevant results.
DDP
EDT is the Event Dispatch Thread. Read the section from the Swing tutorial on "Concurrency" for more information: http://java.sun.com/docs/books/tutorial/uiswing/TOC.html
camickr
Thanks again, camickr! :D
DDP
For active rendering (where you need to control exactly when your component is painted), sometimes adding a `Canvas` to a Swing container *is* appropriate.
finnw
A: 

Override addNotify() and create the BufferStrategy from there:

public ChronosDisplay (String str)
{
    mapName = str;
    new Thread(this).start();
    // Note: no createBufferStrategy() or setVisible()
}

public void addNotify() {
    super.addNotify();
    createBufferStrategy(2);
}
finnw
Hmm, interesting. I'll have to try that out sometime :)
DDP