Gavin Gnaster
Gavin Gnaster

Reputation: 135

How to stop Swing from opening a new frame?

I'm writing a Java text adventure and using Java Swing as a way to display a simple user GUI as the game play screen. I want to have three different windows, one as a start screen, one for a character creation screen where the user inputs a name and some attributes, and one where the game actually takes place.

I want to write each screen in a separate class to increase the organization and readability of my code. However whenever I click on the JButton to go to the next screen a completely new JFrame opens with the content. How can I write my GUI so that all of the screen changes take place in just one frame? Is Java supposed to function like this?

I've looked through at least a couple dozen Java Swing forum questions but still cant find out what I'm doing wrong with my Java swing implementation.

package guiPackage;

import javax.swing.*;
import thingsPackage.Player;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class StartGame extends JFrame {

JFrame Game;
JPanel buttonMenu, screen;
JButton newGame, settings, exit, loadGame;


    public StartGame() {

    Game = new JFrame();
    Game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
    Game.setVisible(true);
    Game.setSize(750, 750);
    Game.setLocationRelativeTo(null);

    screen = new JPanel();
    screen.setVisible(true);

    TitleScreenHandler ts = new TitleScreenHandler();

    buttonMenu = new JPanel();

    newGame = new JButton("New Game");
    newGame.addActionListener(ts);
    loadGame = new JButton("LoadGame");
    loadGame.addActionListener(ts);


    settings = new JButton("Settings");
    settings.addActionListener(ts);

    exit = new JButton("Exit");
    exit.addActionListener(ts);

    Game.add(screen);
    screen.add(buttonMenu, BorderLayout.SOUTH);
    buttonMenu.add(newGame);
    buttonMenu.add(loadGame);
    buttonMenu.add(settings);
    buttonMenu.add(exit);

}


public class TitleScreenHandler implements ActionListener{
    public void actionPerformed(ActionEvent titleScreenEvent) {

        if (titleScreenEvent.getSource() == newGame) {
            buttonMenu.setVisible(false);
            CharacterCreator newCharacter = new CharacterCreator();

        }
        else if (titleScreenEvent.getSource() == loadGame) {
            buttonMenu.setVisible(false);
        }
        else if (titleScreenEvent.getSource() == settings) {
            buttonMenu.setVisible(false);

        }
        else if (titleScreenEvent.getSource() == exit){
            System.out.println("goodbye");
            System.exit(0);
        }
    }
}
}

package guiPackage;

import javax.swing.*;
import java.awt.*;
import java.util.Scanner;

public class CharacterCreator extends StartGame {

JTextField newName;
JPanel creatorScreen;
Scanner scan = new Scanner(System.in);

public CharacterCreator() {

    creatorScreen = new JPanel();
    //creatorScreen.setVisible(true);

    newName = new JTextField("Create a charactor");
    //newName.setLocation(null);

    screen.add(creatorScreen);
    creatorScreen.add(newName);
}
public String setCharacterName(){
    String characterName = "";
    return characterName;
}
}

Upvotes: 0

Views: 473

Answers (2)

PiBurner
PiBurner

Reputation: 75

In short, you should try using jLayeredPane and multiple jPanels, not multiple frames. If you're using Netbeans, check out my guide to making GUIs at: http://philofjava.webstarts.com/

Upvotes: 0

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

Is Java supposed to function like this?

Your code is only doing what you're telling it to, and you've several problems in your code including one problem here:

public class CharacterCreator extends StartGame {

You're misusing inheritance by havng the CharacterCreator class extend from StartGame. You seem to be doing this to allow communication between classes, but that is not what inheritance is for, and in doing this you're child class is calling the parent class's constructor, creating more windows than you want or need. The solution is to not use inheritance here but rather to pass references to where they are needed.

Also please check out The Use of Multiple JFrames, Good/Bad Practice? since your application should have only one main application window or JFrame. Any child windows should be JDialogs, not JFrames.

Another issue: StartGame extends JFrame and also holds a JFrame variable -- too many JFrames, and best to get rid of one or the other. Usually you don't want to create classes that extend a top-level window since you'll find yourself painting yourself in a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. In fact, I would venture that most of the Swing GUI code that I've created and that I've seen does not extend JFrame, and in fact it is rare that you'll ever want to do this. More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.

Other separate and unrelated issues:

  • You appear to be combining an event driven GUI with a console GUI since you're using a Scanner object initiated with System.in. This is not a good idea since these two programming paradigms do not easily play nice with each other, and instead it is best to stick with one or the other, either a linear console program or an event-driven GUI.

Upvotes: 4

Related Questions