Недопустимое исключение состояния при создании новой стратегии буферизации

Когда я пытаюсь понять, как использовать буферные стратегии, и в целом просто улучшаю то, как я пишу свой код и очищаю вещи. Когда я запускаю следующий код, я получаю сообщение об ошибке, когда я "createBufferStrategy(3)"

    package Game1Test;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.io.IOException;

import javax.swing.*;

public class Base extends Canvas implements Runnable{

    private static final long serialVersionUID = 1L;
    private boolean running = false;
    int ticks = 0;

    public Base(JFrame f) {
        setSize(f.getWidth(),f.getHeight());
        start();
    }

    public void start(){
        running = true;
        new Thread(this).start();
    }
    public void stop(){

    }
    public void run(){
        while(running){
            ticks++;
            System.out.println(ticks);
            render();

                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
    }
    public void render(){
        BufferStrategy bs = getBufferStrategy();
        Graphics g;
        if(bs == null){
            createBufferStrategy(3);
            requestFocus();
            return;
        }
        bs.show();
    }



}

Затем к базе добавляется:

package Game1Test;

import java.awt.*;

import javax.swing.JFrame;

public class Screen extends JFrame{

    public final int GAME_WIDTH = 400;
    public final int GAME_HEIGHT = 400;
    public Dimension gameDim = new Dimension(GAME_WIDTH,GAME_HEIGHT);
    final String gameName = "Test";

    public Screen(){
        setSize(gameDim);
        setTitle(gameName);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setLayout(new GridLayout());
        setVisible(true);
        setLocationRelativeTo(null);
    }
    public static void main(String[] args){
        Screen s = new Screen();
        s.add(new Base(s));
    }
}

Я получаю следующую ошибку:

Exception in thread "Thread-2" 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 Game1Test.Base.render(Base.java:46)
    at Game1Test.Base.run(Base.java:33)
    at java.lang.Thread.run(Unknown Source)

Может кто-нибудь, пожалуйста, скажите мне, почему это происходит? а может быть решение этой проблемы?

Спасибо


person matthewtory    schedule 02.06.2012    source источник
comment
согласно API, это исключение выдается, если компонент не отображается.   -  person Hovercraft Full Of Eels    schedule 03.06.2012
comment
@HovercraftFullOfEels Что именно это означает?   -  person matthewtory    schedule 03.06.2012


Ответы (3)


Взгляните на API, это исключение возникает, если компонент не отображается. В данном случае это когда Canvas.peer равно null. Взглянув на поле peer, вы увидите, что

Одноранговый узел устанавливается, когда Component добавляется в контейнер, который также является одноранговым.

Поскольку вы запускаете поток обновления из конструктора вашего компонента, render может быть вызвано до того, как ваш компонент будет добавлен в другой контейнер, что будет означать, что peer равно null, а затем будет выброшен IllegalStateException.

person Jeffrey    schedule 02.06.2012
comment
Извините, если я туплю, но когда добавляется компонент, вот что меня смущает, когда я должен вызывать метод рендеринга? - person matthewtory; 03.06.2012
comment
Вы должны вызывать метод render только после добавления Base в контейнер. В коде, который вы нам показали, Base никогда не добавляется в контейнер. - person Jeffrey; 03.06.2012
comment
Я только что добавил базовый код, было бы лучше, если бы я поместил все это в один класс? - person matthewtory; 03.06.2012
comment
@ grimrader22 Проблема в том, что в промежутке между созданием Base и его добавлением в Screen поток обновления, который вы начали, возможно, уже вызвал render. Вам нужно либо вызвать start отдельно от конструктора Base, либо добавить Base к JFrame в конструкторе Base перед вызовом start. - person Jeffrey; 03.06.2012
comment
поэтому я должен вызвать метод запуска. В основном классе, где находится основной метод? - person matthewtory; 03.06.2012
comment
@ grimrader22 Да, убедитесь, что вы вызываете его после добавления Base к Screen. - person Jeffrey; 03.06.2012

По моему опыту с этой ошибкой и с кодом, который вы пишете, вам не хватает функции кадра.

Добавьте, где находятся ваши кадры (например: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);), и добавьте функцию frame.add(game);

В этом примере у меня Display game = new Display();, но в зависимости от того, какая у вас переменная для нового дисплея, она может отличаться.

person ANBHOO    schedule 14.07.2012

У меня было точно такое же исключение, но я узнал, что это произошло из-за того, что моя видимость JFrame была случайно установлена ​​​​на false.

поэтому вставьте setVisible (true); починил это.

person Luke    schedule 02.02.2019