BufferyStrategy returns an error

820 views Asked by At

I am trying to make a game so I started creating all the drawing methods and ways, so I can begin with the graphics work, but when I am creating my bufferyStrategy, java returns an error.

Why is that error happening?

Exception in thread "Thread-0" java.lang.IllegalStateException: Component must have a valid peer
    at java.awt.Component$FlipBufferStrategy.createBuffers(Unknown Source)
    at java.awt.Component$FlipBufferStrategy.<init>(Unknown Source)
    at java.awt.Component$FlipSubRegionBufferStrategy.<init>(Unknown Source)
    at java.awt.Component.createBufferStrategy(Unknown Source)
    at java.awt.Canvas.createBufferStrategy(Unknown Source)
    at java.awt.Component.createBufferStrategy(Unknown Source)
    at java.awt.Canvas.createBufferStrategy(Unknown Source)
    at Game.render(Game.java:28)
    at Game.run(Game.java:17)
    at Game$1.run(Game.java:45)
    at java.lang.Thread.run(Unknown Source)

This is the source:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;


public class Game extends Frame {

    public boolean playing = false;

    public Game() {
    }

    public void run() {
        while (playing) {
            update();
            render();
        }
    }

    public void update() {

    }

    public void render() {
        BufferStrategy b = null;
        if (super.getBufferStrategy() == null) {
            super.createBufferStrategy(3);
        }
        b = super.getBufferStrategy();
        Graphics2D g = (Graphics2D) b.getDrawGraphics();
        g.setColor(Color.BLACK);
        g.fillRect(0,  0, getWidth(), getHeight());
        g.dispose();
        b.show();
    }


    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Game game = new Game();
                game.playing = true;
                game.run();
            }
        }).start();
    }

}

and the parent class:

import java.awt.Canvas;
import java.awt.Dimension;

import javax.swing.JFrame;


public class Frame extends Canvas {

    private JFrame frame = new JFrame();

    public Frame() {
        frame.setTitle("Finland2D");
        frame.setPreferredSize(new Dimension(765, 500));
        frame.pack();
        super.setVisible(true);
        frame.setVisible(true);
    }

    public JFrame getFrame() {
        return this.frame;
    }

}

What am I doing wrong?

2

There are 2 answers

1
wangdq On

Reviewed your code,I suggest you to give every class a good name.

Bad-style naming ,such as Frame extends Canvas ,will make a mess.

And If you use Swing,there built-in buffered-Strategy for you,like double-buffered strategy.

please give more information.

currently,I refactored your code ,and make a sample as follow:

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 * this code still Need to improve 
 * deal with Thread related code
 *
 */
public class Game extends Canvas implements Runnable{

    public static void main(String[] args) {
        //GUI EDT thread
        SwingUtilities.invokeLater(new Runnable(){

            @Override
            public void run() {
                JFrame frame = new JFrame("Finland2D");
                frame.setPreferredSize(new Dimension(765, 500));
                final Game game = new Game();
                game.playing = true;
                frame.add(game);
                frame.pack();
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.addWindowListener(new WindowAdapter(){

                    @Override
                    public void windowClosing(WindowEvent e) {
                        // TODO Auto-generated method stub

                        game.finish();
                        System.exit(0);
                    }

                });
                //start game thread
                new Thread(game).start();
            }
        });
    }


    public Game() {
    }
    @Override
    public void run() {
        while (playing) {
            update();
            render();
        }
    }
    public void finish() {
        playing = false;
    }
    public void update() {

    }

    public void render() {
        BufferStrategy b = null;
        if (super.getBufferStrategy() == null) {
            super.createBufferStrategy(3);
        }
        b = super.getBufferStrategy();
        Graphics2D g = (Graphics2D) b.getDrawGraphics();
        g.setColor(Color.BLACK);
        g.fillRect(0,  0, getWidth(), getHeight());
        g.dispose();
        b.show();
    }
    private static final long serialVersionUID = 1L;
    public boolean playing = false;
}
0
StoopidDonut On

It looks like your render() is getting invoked before your Canvas (Frame) is added to a peer component.

Try explicitly adding your 'Frame' instance to the container, JFrame within your Frame constructor:

private JFrame frame = new JFrame();

    public Frame() {
            frame.setTitle("Finland2D");
            frame.setPreferredSize(new Dimension(765, 500));
            frame.pack();
            super.setVisible(true);
            frame.setVisible(true);

            //Explicitly add this to the container
            frame.add(this);
        }

I tried executing it with it and I get no exception and a Black screen.