创建新的Bufferstrategy时出现了非法状态异常

8

当我试图弄清楚如何使用缓冲策略,并且改进代码并清理代码时。当我运行以下代码时,我在“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();
    }



}

然后将Base添加以下内容:
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));
    }
}

I get the following error:

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)

请问有人能告诉我这是为什么吗?可能能提供解决此问题的方法吗?

谢谢。


根据API,如果组件不可显示,则会抛出此异常。 - Hovercraft Full Of Eels
@HovercraftFullOfEels 这句话的确切含义是什么? - Matthew Tory
3个回答

10
查看API,如果组件无法显示,则会抛出此异常。在这种情况下,当Canvas.peernull时会出现此情况。查看peer字段,得知:

当将Component添加到一个同时也是对等体的容器中时,该对等体就被设置了。

由于您从组件的构造函数开始更新线程,因此可能会在将组件添加到其他容器之前调用render,这意味着peernull,然后会抛出IllegalStateException异常。

抱歉如果我有些愚蠢,但是组件是什么时候被添加的,这就是我困惑的地方,我应该什么时候调用渲染方法? - Matthew Tory
你应该只在 Base 被添加到容器后才调用 render 方法。在你向我们展示的代码中,Base 从未被添加到容器中。 - Jeffrey
我刚刚添加了基础代码,如果我把它们全部放在一个类中会更好吗? - Matthew Tory
@grimrader22 问题在于,在你创建“Base”并将其添加到“Screen”的时间之间,你启动的更新线程可能已经调用了“render”。你需要单独从“Base”的构造函数中调用“start”,或者在调用“start”之前将“Base”添加到“JFrame”中。 - Jeffrey
那我应该在主类中的主方法中调用启动方法吗? - Matthew Tory
@grimrader22 没错,确保在将你的“Base”添加到“Screen”之后再调用它。 - Jeffrey

2

根据我的经验,结合您的代码,您可能缺少一个框架函数。

在您的帧中添加以下内容(例如:frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);),并添加函数frame.add(game);

在这个例子中,我的是Display game = new Display();,但根据您为新显示设置的变量,可能会有所不同。


0

我遇到了完全相同的异常,但是我发现这是因为我的JFrame可见性意外地设置为了false。

所以加入setVisible(true);就解决了问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接