Neuen Frame öffnen und gleichzeitig aktuellen schließen

Hi Leute,

ich brauche dringend Hilfe, ich bin am Verzweifeln!

Ich bin dabei ein Programm zu schreiben. Ist ein Tetris-Spiel mit Hauptmenü. Ich habe mir also eine GUI für das Menü erstellt und dort Buttons eingebaut. Die Buttons sollen eine andere Menüseite (also einen neuen Frame) öffnen. Und das tun sie auch, kein Thema. Nur dann kommt mein Problem:

Ich möchte also den neuen Frame öffnen (kein Problem), dabei aber den ersten schließen, so dass nur der neue offen ist.
Dann habe ich im neuen Frame wieder einen Button, welcher wieder den ersten Frame öffnen und den aktuellen schließen soll.

Klingt ganz einfach, nur gibt es da einen Knackpunkt, an dem es bei mir scheitert:
Ich habe einen Class für den ersten Frame, eine für den zweiten Frame und in einem dritten Frame habe ich meine ActionListener und WindowListener, wo ich halt alle Aktionen von Buttons und die Fenster-Optionen für alle Frames regle. Daher kann ich aber auch nicht einfach sagen das „this“-Fenster disposed werden soll, weil ich ja den Frame in einer anderen Class erstellt habe.

Help me please :frowning:

Ist mein Problem so nachvollziehbar? oder soll ich den Code noch hochladen?

Gruß
Fleckvieh

Jein. Irgendwo müssen halt irgendwelche Referenzen woanders hingereicht werden, oder ggf. Listener woanders erstellt oder angehängt werden. Ein paar Zeilen Code (zumindest den Teil mit der Erstellung der Frames und der relevanten Listener) würde wohl nicht schaden. Aber vielleicht noch vorneweg: Für “Einstellungsfenster” verwendet man üblicherweise Dialoge: http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html Die kann man auch modal machen, dann erspart man sich vielleicht einiges von dem, was du beschreibst…

Hier ist meine Class für die Listener: http://pastebin.com/WDdEzzHy

Meine Main-Frame-Class: http://pastebin.com/Rfd96g6r

Und die Class für die “zweite Seite”: http://pastebin.com/nhbbAzSb

geht halt erstmal nur um den dritten Button, weil der die Options öffnen soll.

Ich suche also eine Möglichkeit in dieser Zeile:

    new Options_Frame();
}```

zu sagen, dass er gleichzeitig den Main_Frame schließen soll. Und andersrum bei dem "Back to menu"-Button

In deiner aktuellen GUI-Konstellation wäre auch denkbar, den Einstellungsdialog (Options) ein ein separates JPanel einzubauen (nicht in einen JFrame/JDialog) und dann mit CardLayout zu arbeiten.
Dann wäre alles immer im gleichen Fenster.

Da man davon ausgehen muss, dass das NICHT nur ein Test/Dummybeispiel ist:

  • Variablennamen klein schreiben
  • Variablen- und Klassennamen ohne_Unterstrich verwenden
  • Variablennamen verwenden, die mehr aussagen als “button1” usw. Warum nicht “startButton”, “menuButton”, “exitButton”…?

Von JFrame zu erben ist fast nie notwendig, und wenn es nicht notwendig ist, sollte man es auch nicht tun.

Abgesehen davon wird es SEHR schnell SEHR unübersichtlich, wenn man für alles einen Riesen-ActionListener verwendet, in dem per ActionCommand irgendwelche entscheidungen getroffen werden. Häufig kann man solche Funktionen mit Actions http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html besser umsetzen.

Die pragmatische Lösung für deine Frage wäre: Übergib’ eine Referenz auf den mainFrame an den ActionListener

public class ListenerAdapter implements WindowListener, ActionListener{
 
    private MainFrame mainFrame;

    public ListenerAdapter(MainFrame mainFrame)
    {
        this.mainFrame = mainFrame;
    }
    ....           
    public void actionPerformed(ActionEvent e){
    ....                  
         if(e.getActionCommand().equals("3")){
             mainFrame.dispose(); // oder setVisible(false); ?
             new Options_Frame();
         }
    }

aber das würde die schon etwas fragwürdige Struktur nicht besser machen. Stattdessen solltest du ggf. auf diese Listener-Klasse verzichten. Du könntest GROB sowas machen wie

public class MainFrame {
    ...
    // Hier braucht man keine Button-Referenzen
    ...

    public MainFrame() {
    ...
        final JFrame window = new JFrame();  
        window.setTitle("Tetris"); 
        ...

        JButton controlsButton = new JButton("Controls");
        controlsButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                 window.setVisible(false); // oder dispose();
                 new OptionsFrame(); 
            }
        });
        somePanel.add(controlsButton);


....
        window.setVisible(true);
    }
}

Aber das ist erstmal nur ein Vorschlag…

Für dein eigentliches Problem (das weiterschalten zur nächsten Menüseite) solltest du dir mal das CardLayout ansehen. Es ist nicht notwendig einen neuen Frame zu erstellen. Guck dir mal das beispiel an das ich angehängt habe.
Außerdem mal ins Byte-Welt-Wiki gucken, da gibts ein CardLayout-Tutorial

Noch ein CardLayout-Demo, mit einem an dein Programm angelehnten Beispiel von mir:
CardLayout-Demo.zip (6,9 KB)

Edit:
Ach… der Quelltext liegt in der Jar-Datei.

Noch mal Edit: Defekten Link aktualisiert.