Java Buffers have not been created Problem

Hallo ich bin relativ unreif was Java angeht und wollte mal wissen warum ich manchmal diese Exception bekomme.

[SPOILER]Exception in thread "main" java.lang.IllegalStateException: Buffers have not been created at sun.awt.windows.WComponentPeer.getBackBuffer(Unknown Source) at java.awt.Component$FlipBufferStrategy.getBackBuffer(Unknown Source) at java.awt.Component$FlipBufferStrategy.updateInternalBuffers(Unknown Source) 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.Window.createBufferStrategy(Unknown Source) at java.awt.Component.createBufferStrategy(Unknown Source) at java.awt.Window.createBufferStrategy(Unknown Source) at secret.game.main.Frame.make_strat(Frame.java:24) at secret.game.main.Main.main(Main.java:14)
[/SPOILER]

Die Exception kommt ca. 1 von 8-9 Start Versuche trotzdem ist sie ein Dorn im Auge.
Ich kann mir gut vorstellen dass die Lösung nicht wirklich Komplex ist aber trotzdem komm ich nicht drauf :smiley: meine Vermutung ist dass ich die MakeStrat Methode nicht so schön plaziert hab da manchmal der Kompiler keine Strat erstellen kann bin mir aber nicht ganz sicher… es würde mich freuen wenn ihr mir helfen könnt.

// Die Main Klasse
[SPOILER]```public class Main{

public static void main(String[] args)
{
	// Create new Frame
	Frame frame = new Frame();
	frame.setDefaultCloseOperation(Frame.EXIT_ON_CLOSE);
	frame.setSize(800, 600);
	frame.setResizable(false);
	frame.setLocationRelativeTo(null);
	frame.setVisible(true);
	frame.make_strat();
	
	// Create Gameloop
	while(true)
	{
		// Input
		
		frame.repaint();
		
		// Draw
		
		// Wait 5 - 10ms
		try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
	}
}

}```[/SPOILER]

// Die Frame Klasse
[SPOILER]```import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;

public class Frame extends JFrame{

// Variables
private static final long serialVersionUID = 1L;
private BufferStrategy strat;

// TODO Constructor
public Frame()
{	
	super("Game Title | V0.1");
}

// Create Buffer Strategy
public void make_strat()
{
	createBufferStrategy(2);
	strat = getBufferStrategy();
}

// Draw Screen
public void draw(Graphics g)
{
	g.setColor(Color.BLUE);
	g.drawRect(50, 50, 50, 50);
}

// Repaint Screen
public void repaint()
{
	Graphics g = strat.getDrawGraphics();
	draw(g);
	g.dispose();
	strat.show();
}

}```[/SPOILER]

Danke im vorraus mfg. Secret

was man daran lernen kann, ist, den relevanten Teil der Fehlermeldung in eine Suchmaschine einzutippen:
‘IllegalStateException: Buffers have not been created’
-> exception - java: IllegalStateException - Buffers have not been created - Stack Overflow
und andere, ich nehme an Englisch verständlich,
keine ganz schöne Lösung, aber wohl mit zu leben

edit:
wenn du BufferStrategy einsetzt, bist du mir in diesem Punkt auch nach 10 Jahren schon voraus,
falls das wichtig sein mag, dann doch dazu zusammen mit dem Fehler suchen

Mhm ich hab auch mal danach gesucht.
In manchen Video Tutorials und Spieleforum wird anscheinend BufferStrategy und make_strat() verwendet und zwar ganz selbstverständlicherweise in copy/paste Manier. Aber warum?
Haben die das Verhalten von JFrames verändert in einer der letzten Java-Versionen, dass das plötzlich notwendig wäre?

[QUOTE=TMII]Mhm ich hab auch mal danach gesucht.
In manchen Video Tutorials und Spieleforum wird anscheinend BufferStrategy und make_strat() verwendet und zwar ganz selbstverständlicherweise in copy/paste Manier. Aber warum?
Haben die das Verhalten von JFrames verändert in einer der letzten Java-Versionen, dass das plötzlich notwendig wäre?[/QUOTE]

Also ich weiss nicht so genau aber ich vermute mal es liegt je nach Performance bei mir zumindest ruckelts leicht wenn ich größere Bilder in bewegung setze und auch so kommt mir alles damit viel flüssiger vor :confused: wie gesagt hab nicht viel Ahnung momentan davon aber für copy und paste reichts :smiley: kleiner Scherz ich lern soviel ich kann

[QUOTE=SlaterB;127749]wenn du BufferStrategy einsetzt, bist du mir in diesem Punkt auch nach 10 Jahren schon voraus,
falls das wichtig sein mag, dann doch dazu zusammen mit dem Fehler suchen[/QUOTE]

Ich versteh nicht ganz was meinst du damit worin voraus? jeder benutzt BufferStrategy wenn ich mich nicht irre also fast über all wird das erwähnt.

nun, falls du als Test hier im Forum die Suche damit bemühen wolltest, würdest du nur 14 Themen finden,
freilich insgesamt auch nicht so viele vorhanden :wink: , aber das lese ich schon selten, wenn du meinen Worten glauben magst

oder als Test
Rheinwerk Computing :: Java ist auch eine Insel - index

Suchmaschinensuche ‚site:http: openbook.rheinwerk-verlag.de jpanel‘ findet jede Menge,
‚site:http: openbook.rheinwerk-verlag.de bufferstrategy‘ nichts

im normalen Swing-Tutorial Trail: Creating a GUI With JFC/Swing (The Java™ Tutorials) steht dazu glaube ich nix,
im Extra-Tutorial BufferStrategy and BufferCapabilities (The Java™ Tutorials > Bonus > Full-Screen Exclusive Mode API) meinetwegen

also in kurz: meiner Ansicht nach für normale Zwecke nicht erforderlich, auch eher unbekannt

nebenbei nochmal auf deinen Code geschaut: Frame ist ein schlechter Klassenname,
weil es java.awt.Frame gibt, von dem die Swing-JFrame-Klasse erbt

wie man darin malt empfehle ich nach z.B. diesen (internen :wink: ) Links:
Malen in AWT und Swing – Byte-Welt Wiki
Malen in Swing Teil 1: der grundlegende Mechanismus – Byte-Welt Wiki
http://wiki.byte-welt.net/wiki/Malen_in_Swing_Teil_2:_ein_einfaches_Malprogramm

wo immer du BufferStrategy herhast, lieber weg damit und die Seite dazu meiden :wink:

Um das vielleicht mal „aufzuklären“: Die BufferStrategy wird meistens zum Zusammenhang mit (Fullscreen-Spielen und) „Echtzeit-Spielen“ verwendet. (Ich müßte jetzt nachsehen, meine aber, dass da in Killer Game Programming in Java ein bißchen was dazu steht (und auch in Quaxlis Tutorial?)). Fälle, wo das wirklich „notwendig“ ist, oder einen echten, „greifbaren“ Vorteil bringt, müßte ich mir (nach inzwischen auch >10 Jahren Java mit viel Swing) auch erst zusammensuchen/zusammenreimen. Man könnte wohl auch mit anderen Sachen anfangen, und den „üblicheren“ Weg des „passiven“ Zeichnens gehen, der in den verlinkten Tutorials vorherrscht, aber … da kann ja jeder die Prioritäten anders setzen.

Zur eigentlichen Frage… kann ich nicht viel sagen (habe aber auch nicht alle Links dazu durchgelesen). Beim Überfliegen sahen die Links aus wie „Könnte ein JVM-Bug sein“ (dummerweise steht bei der Top-Stackoverflow-Antwort nicht viel dabei). Aber bei der Fehlerbeschreibung

Die Exception kommt ca. 1 von 8-9 Start Versuche

schrillt bei mir aber die „Threading“-Alarmglocke. So ein undeterministisches Verhalten kann fast nur mit Threading zu tun haben.

Auch wenn die „Projektstruktur“ wohl noch nicht ganz klar ist (wo läuft der Game-Loop, wer macht dort was, welche Klassen gibt es, wer muss wen kennen usw), kannst du mal versuchen, ob das Problem auch dann noch auftritt, wenn man das GUI (wie man es eigentlich immer tun sollte!) auf dem Event-Dispatch-Thread erzeugt (ist erstmal ein Schuss ins Blaue, aber eben ein „einigermaßen educated guess“) :

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

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

public class BufferStrategyMain
{

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
    
    private static void createAndShowGUI()
    {
        GameFrame frame = new GameFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.make_strat();
        
        startGameThread(frame);
    }
    
    private static void startGameThread(final GameFrame frame)
    {
        Thread t = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                runGameLoop(frame);
            }
        });
        t.setDaemon(true);
        t.start();
    }
    
    private static void runGameLoop(final GameFrame frame)
    {
        // Create Gameloop
        while (true)
        {
            // Input

            frame.repaint();

            // Draw

            // Wait 5 - 10ms
            try
            {
                Thread.sleep(10);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
    

}

class GameFrame extends JFrame
{

    // Variables
    private static final long serialVersionUID = 1L;
    private BufferStrategy strat;

    // TODO Constructor
    public GameFrame()
    {
        super("Game Title | V0.1");
    }

    // Create Buffer Strategy
    public void make_strat()
    {
        createBufferStrategy(2);
        strat = getBufferStrategy();
    }

    // Draw Screen
    public void draw(Graphics g)
    {
        g.setColor(Color.BLUE);
        g.drawRect(50, 50, 50, 50);
    }

    // Repaint Screen
    public void repaint()
    {
        Graphics g = strat.getDrawGraphics();
        draw(g);
        g.dispose();
        strat.show();
    }
}

(BTW: „Frame“ umbenannt zu „GameFrame“ - die Klasse „Frame“ gibt es schon in java.awt, das kann verwirrend sein)

Gut danke nochmal für alles ich werd einfach drauf verzichten sollte hoffentlich kein großen Unterschied ausmachen Notfalls werd ich eine andere Möglichkeit aufsuchen.

@SlaterB

Ok gut danke nochmal dann wird dass wohl noch nicht zwingend notwedig sein und was der Name Frame für JFrame angeht hab ich bis jetzt keine Probleme gehabt aber ich werd kein Risiko eingehen :smiley: danke.

Naja wenn du ein JPanel auf dein JFrame legst und darauf zeichnest, dann sollte DoubleBuffering bereits standardmäßig verwendet werden -> also “createBufferStrategy(2);”
Ein Multibuffering kann zwar das ganze weicher erscheinen lassen weil Bilder bereits im Vorraus gezeichnet werden und kurzezeitige Frametime Spitzen dadurch verhindert werden, aber auch die Anzeigeverzögerungen und RAM Anforderungen erhöhen sich linear.
Würde sagen den größten Vorteil hat man von DoubleBuffering das Swing eigentlich standardmäßig bereits verwendet.

Danke werde ich probieren aber dass DoubleBuffering auf JPanel verwendet wird ist mir vollkommen neu hätte ich dass gewusst hätte ich mir ne menge Probleme gespart :smiley: naja aber ich hab nochmal eine Alternative „herausgefunden“

public void make_strat()
{
	try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} // Einfach kurz warten bevor der nächste Durchlauf gemacht wird.
	createBufferStrategy(2);
	strat = getBufferStrategy();
}```

Ist nicht so schön aber es funktioniert trotzdem danke an alle.

Edit: ich bin mir auch nicht ganz sicher ob dass Auswirkungen auf die FPS hat, deshalb dann doch lieber zu JPanel greifen :D.