The button on my screen won't track me towards my GamePane
class. I think it's because of the ActionListener
. I have also heard of using a MouseListener
but I don't know what that is.
GameFrame:
The GameFrame
holds the component for the game screen. This screen won't show up when the start button is pressed.
import java.awt.CardLayout;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GamePane extends JPanel {// *change GamePane to GamePane
// This is were the game screen is made and the player is created.
private static final long serialVersionUID = 1L;
JLabel player = new JLabel();
int playerSpeed = 1;
int FPS = 30;
// Set the timer
// Timer tm = new Timer(1000 / FPS, this);
// tm.start();
// The keys set holds the keys being pressed
private final Set<Integer> keys = new HashSet<>();
public static void main(String[] args) {
// Open the GUI window
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Create a new object and
// run its go() method
new GamePane().go();
}
});
}
GamePane() {
// Run the parent class constructor
super();
// Allow the panel to get focus
setFocusable(true);
// Don't let keys change the focus
setFocusTraversalKeysEnabled(false);
}
/**
* The frame that shows my game
*/
protected void go() {
// Setup the window
JFrame GameFrame = new JFrame();
// Add this panel to the window
GameFrame.setLayout(new CardLayout());
GameFrame.setContentPane(this);
// Set the window properties
GameFrame.setTitle("game");
GameFrame.setSize(800, 400);
GameFrame.setLocationRelativeTo(null);
GameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GameFrame.setVisible(true);
GameFrame.add(new ButtonPane(GameFrame), "game");
}
}
ButtonPane:
This is were the pane containing the button is created. The button is also created in the button pane.
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonPane extends JPanel {
private static final long serialVersionUID = 1L;
private JButton startBTN;//Calls the JButton
JFrame game;
public ButtonPane(JFrame MainFrame) {
game = MainFrame;
setLayout(new GridBagLayout());
MainFrame.setBackground(Color.BLUE);//Sets the menu stages color blue
startBTN = new JButton("Start");//Creates a new button
add(startBTN);//Adds the button on the startStage
startBTN.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button pressed");
// ((CardLayout) game.getContentPane().getLayout()).show(game.getContentPane(), "game");
if (game.getContentPane().getLayout() instanceof CardLayout) {
System.out.println("is card layout");
CardLayout layout = (CardLayout) getParent().getLayout();
layout.show(game.getContentPane(), "game");
}
}
});
}
}
There is to much going on in your code and too much "guess work". You've also coupled you code together making it near impossible to maintain or manage.
Step back and reassess you design. You need:
- A container which acts as the "main view", this is the container which is used to switch between various views, it acts as the main "controller" for the navigation
- A menu component
- A game component
- A frame to hold the "main view"
Let's start with the frame. The frame should be as dumb as possible. It's sole job is to get the "main view" on the screen, very little else
Maybe something like...
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
The MainPane
(or main view) doesn't care about the frame, so we don't need to pass anything else to it. Because the "main view" is acting as our navigation controller, you want to avoid exposing it to other views. Those views shouldn't care how the navigation works, only that they can move between views.
So, instead of passing MainPane
to the subviews, we create a concept of "navigation controller" which is used to allow the subviews to make requests about what they would like to do, it's then up to the implementation to make that work.
public interface NavigationController {
public void showGame();
public void showMenu();
}
MainPane
then acts as the "main container" for all the other top level subviews and the NavigationController
public class MainPane extends JPanel implements NavigationController {
public MainPane() {
setLayout(new CardLayout());
add(new MenuPane(this), "menu");
add(new GamePane(this), "game");
}
protected CardLayout getCardLayout() {
return (CardLayout) getLayout();
}
@Override
public void showGame() {
getCardLayout().show(this, "game");
}
@Override
public void showMenu() {
getCardLayout().show(this, "menu");
}
}
It's whole responsibility is to facilitate the switching between the top level subviews
Then our subviews....
public class MenuPane extends JPanel {
private NavigationController controller;
public MenuPane(NavigationController controller) {
this.controller = controller;
setLayout(new GridBagLayout());
JButton btn = new JButton("Do you want to play a game?");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.showGame();
}
});
add(btn);
}
}
public class GamePane extends JPanel {
private NavigationController controller;
public GamePane(NavigationController controller) {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JLabel("Ready player one"), gbc);
gbc.weighty = 0;
JButton btn = new JButton("Had enough");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.showMenu();
}
});
add(btn, gbc);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
These views do a single job (what ever that job is) and delegate the navigation responsibility back to the NavigationController
If you're wondering, MenuPane
would be your equivalent of ButtonPane
Runnable Example...
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface NavigationController {
public void showGame();
public void showMenu();
}
public class MainPane extends JPanel implements NavigationController {
public MainPane() {
setLayout(new CardLayout());
add(new MenuPane(this), "menu");
add(new GamePane(this), "game");
}
protected CardLayout getCardLayout() {
return (CardLayout) getLayout();
}
@Override
public void showGame() {
getCardLayout().show(this, "game");
}
@Override
public void showMenu() {
getCardLayout().show(this, "menu");
}
}
public class MenuPane extends JPanel {
private NavigationController controller;
public MenuPane(NavigationController controller) {
this.controller = controller;
setLayout(new GridBagLayout());
JButton btn = new JButton("Do you want to play a game?");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.showGame();
}
});
add(btn);
}
}
public class GamePane extends JPanel {
private NavigationController controller;
public GamePane(NavigationController controller) {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JLabel("Ready player one"), gbc);
gbc.weighty = 0;
JButton btn = new JButton("Had enough");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.showMenu();
}
});
add(btn, gbc);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}