# BufferStragety Fehler: Component must have a valid peer



## Revenant (1. Apr 2007)

Hi,

bräuchte mal wieder Hilfe... ich will ne einfache BufferStrategy verwenden, scheitere jedoch aufgrund eines mir unbekannten Fehlers. Der Code ist echt klein, ich frag mich was schief geht?

Exception in thread "main" java.lang.IllegalStateException: Component must have a valid peer
	at java.awt.Component$FlipBufferStrategy.createBuffers(Component.java:3362)
	at java.awt.Component$FlipBufferStrategy.<init>(Component.java:3337)
	at java.awt.Component.createBufferStrategy(Component.java:3246)
	at java.awt.Canvas.createBufferStrategy(Canvas.java:166)
	at java.awt.Component.createBufferStrategy(Component.java:3178)
	at java.awt.Canvas.createBufferStrategy(Canvas.java:141)
	at GameCanvas.<init>(GameCanvas.java:23)
	at LevelControl.<init>(LevelControl.java:20)
	at Ships3.main(Ships3.java:8)


```
public class GameCanvas extends Canvas
{
    private BufferStrategy strategy;
    private Graphics2D g;
    
    /**creates the canvas and the used BufferStrategy
    GameCanvas()
    {
        // size of canvas
        this.setBounds(0,0,800,600);
        this.setBackground(Color.BLACK);
        // active rendering
        this.setIgnoreRepaint(true);
        // BufferStrategy
        createBufferStrategy(2);
        strategy = getBufferStrategy();
    }
    
    /**returns the (by the canvas accelerated) graphics context to which all other classes should draw to
    public Graphics2D getGraphicsContext()
    {
        return g = (Graphics2D) strategy.getDrawGraphics();
    }
    
    /**draws the accelerated canvas, note: this method should be called after all the other classes finished drawing
    public void draw()
    {
        // finally, we've completed drawing so clear up the graphics
        // and flip the buffer over
        g.dispose();
        strategy.show();
    }
}
```


----------



## Wildcard (1. Apr 2007)

Bin mir jetzt nicht 100% sicher, aber soweit ich weiß müsste vorher addNotify() aufgerufen werden.
Das solltest du jedoch nicht selbst tun sondern von AWT erledigen lassen.
Dazu muss die Canvas einen Parent erhalten und dieser Parent sichtbar gemacht werden.


----------



## Revenant (1. Apr 2007)

yo, das hab ich beim googeln auch gefunden. Meine Spiellogik versucht das auch:


```
public class LevelControl extends Thread
{
    GameCanvas canvas;
    
    public LevelControl()
    {
        // create main frame/panel/canvas
        JFrame frame = new JFrame("Ships3");
        frame.setPreferredSize(new Dimension(800,600));
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        frame.pack();
        frame.setResizable(false);
        // make stuff visible
        frame.setVisible(true);
        
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(800,600));
        panel.setLayout(null);
        canvas = new GameCanvas();
        panel.add(canvas);       
        frame.add(panel);
    }
    
    /**THE GAME LOOP
    public void run()
    {
        canvas.getGraphicsContext();
    }
}
```

Edit: is das nicht irgendwie unschön? Erst das Frame sichtbar machen und dann noch was hinzufügen?


----------



## Chris_1980 (1. Apr 2007)

Du darfst createBufferStrategy() nicht im Constructor aufrufen. 
Zum Zeitpunkt des Constructoraufrufs ist das Canvas logischerweise niemals Sichtbar. 
Schreib das gesondert in ne Methode, die du aufrufst, nachdem du dein Canvas auf den Frame geadded hast und dieser sichtbar ist.


----------



## Revenant (1. Apr 2007)

Ok, so funktioniert es, vielen Dank.

Ist es legitim das createBufferStragety() in der canvas.getGraphicsContext() aufzurufen? Denn das würde dann ja bei jedem Threaddurchlauf passieren (Performance).


----------



## Chris_1980 (1. Apr 2007)

Also die BufferStrategy muß nur einmal erstellt werden.  Ich seh da keinen Grund das bei jedem Durchlauf zu tuen, aber wie sich das auswirkt weiß ich nicht.

mach doch einfach eine Methode

```
public void createStrategy()
{
    createBufferStrategy(2);
    strategy = getBufferStrategy();
}
```

Und die rufst du dann einmal nachdem du frame.setVisible(true) gemacht hast auf.


----------

