I'm developing a game, written in java swing. I create a class MainGUI that extends JFrame, to contain the multiple screens of the application. In other classes, I create different JPanels, like StartPanel and GamePanel, that are inserted during execution in the MainGUI. In the StartPanel, when the user entered the nickname, a button allows to switch to GamePanel.
The problem is that I can't switch panels. I try to use CardLayout, but when I press a button in a panel, I can't handle the event in the MainGUI and show a different panel.
I used the MVC design pattern, so there are 3 packages (controller, model, view) that communicate with each other thanks to the classes ControllerForModel, ControllerForView, View and Model, that implement the relevant interface.
The application is started thanks to the class Main in controller package.
package frogger.view;
import java.awt.Color;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainGUI extends JFrame {
//---------------------------------------------------------------
// STATIC FIELDS
//---------------------------------------------------------------
public MainGUI(String title) {
super(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
StartPanel startPane = new StartPanel();
Container contPane = this.getContentPane();
contPane.add(startPane);
this.pack();
} //end constructor
This is the code of MainGUI class, and it only shows the StartPanel.
package frogger.view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class StartPanel extends JPanel {
//---------------------------------------------------------------
// CONSTANTS FIELDS
//---------------------------------------------------------------
private final static String LOGO_PATH = "img/logo.png";
//---------------------------------------------------------------
// STATIC FIELDS
//---------------------------------------------------------------
private static Image logoImg;
private static JLabel logoLabel;
private static JLabel newGameLabel;
private static JLabel loadGameLabel;
private static JLabel newGameLabelInCurrentDisplayedPanel;
private static JButton newGameButton;
private static JButton loadGameButton;
private static JButton newGameButtonInCurrentDisplayedPanel;
private static JTextField nicknameTextField;
private static JPanel currentDisplayedPanel;
public StartPanel() {
//todo
super();
this.setLayout(new GridBagLayout());
loadImage(LOGO_PATH);
this.logoLabel = new JLabel(new ImageIcon(this.logoImg.getScaledInstance(400, 200, Image.SCALE_SMOOTH)));
locateLogoLabel();
this.newGameLabel = new JLabel("Start a new game:");
locateNewGameLabel();
this.newGameButton = new JButton("New");
this.newGameButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleShowNewGamePanelEvent();
}
});
locateNewGameButton();
this.loadGameLabel = new JLabel("Load a previously saved game:");
locateLoadGameLabel();
this.loadGameButton = new JButton("Load");
this.loadGameButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleShowLoadGamePanelEvent(e);
}
});
locateLoadGameButton();
this.currentDisplayedPanel = new JPanel(new GridBagLayout());
this.currentDisplayedPanel.setPreferredSize(new Dimension(400, 100));
locateCurrentDisplayedPanel();
} //end constructor
//---------------------------------------------------------------
// INSTANCE METHODS
//---------------------------------------------------------------
private void handleNewGameEvent() {
//todo
}
private void handleLoadGameEvent() {
//todo
}
private void handleShowNewGamePanelEvent() {
System.out.println("New game button pressed");
this.newGameLabelInCurrentDisplayedPanel = new JLabel("Inserisci il tuo nickname:");
locateNewGameLabelInCurrentDisplayedPanel();
this.nicknameTextField = new JTextField(15);
locateNicknameTextFieldInCurrentDisplayedPanel();
this.newGameButtonInCurrentDisplayedPanel = new JButton("Conferma");
this.newGameButtonInCurrentDisplayedPanel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleNewGameEvent();
}
});
locateNewGameButtonInCurrentDisplayedPanel();
this.currentDisplayedPanel.revalidate();
this.currentDisplayedPanel.repaint();
}
private void handleShowLoadGamePanelEvent() {
System.out.println("Load game button pressed");
}
} //end class
This is the code of StartPanel.
package frogger.controller;
import frogger.view.MainGUI;
public class Main {
public static void main(String[] args) {
ControllerForView.getInstance().openGameWindow();
}
}
And this is the code of the class Main that starts the application.
The question is: how can I switch from StartPanel to GamePanel when the user press newGameButton? In other words, how can I implement the method handleNewGameEvent() to dialogue with the MainGUI?
Thanks everyone in advance
I tried to use CardLayout in MainGUI to show a panel and another, but I don't know how to communicate to MainGUI that has to switch panel when the user clicks on a button in a panel describe with an external class.
As I mentioned in comment, I would use a CardLayout, and I would try to separate control of the card layout from the view, using MVC, or in my example below, a more simplified model-controller. Here, any class that has access to the controller can control what the card layout displays:
MainGUI.java
This creates the components, connects them, and starts them.
ConcreteController.java
This is the class that controls what the card layout displays.
CardView.java
The GUI class that holds the cardsPanel, the one that uses a CardLayout, and that displays the cards JPanels. It also has previousButton, nextButton and a JComboBox to allow selection of the visualized card
RandomPanel.java
A dummy JPanel that simply displays text that is passed into its constructor with a randomly created background color. It has a nextButton to show that it can interact with the CardLayout that contols its display
Complete MRE
The complete program in one single copy/paste compile/run file: