I am making a simple game using a JFrame
. I have made a simple "Start" screen which basically consists of a String
and a JButton
. I am picking up the button click with the actionPerformed(ActionEvent e)
method. I don't know how to change the cards using a button click. This may seem like a simple problem to solve, but the twist comes with this: My main JFrame, my StartScreen and my JPanel where the game takes place are all in separate files. My main file, Virus.java, is where I create the JFrame
. My file VirusGamePanel.java is where the game takes place. My file StartScreen.java is the screen with the button. I want to change 'cards' to the game screen when the player clicks the button. How can I do this?
My StartScreen.java file:
package virus;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
import javax.swing.JButton;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.CardLayout;
public class StartScreen extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
JButton start = new JButton("Start");
public StartScreen(){
start.addActionListener(this);
start.setBounds(new Rectangle(400,300,100,30));
this.add(start);
}
public void paint(Graphics g){
super.paint(g);
g.setFont(new Font("Impact",Font.BOLD,72));
g.setColor(Color.MAGENTA);
g.drawString("Virus",275,300);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==start)
{
//what to do here?
}
}
}
My Virus.java file:
package virus;
import javax.swing.*;
import java.awt.CardLayout;
import virus.StartScreen;
public class Virus extends JFrame{
private static final long serialVersionUID =1L;
JFrame jf = new JFrame("Virus");
static JPanel thegame = new JPanel(new CardLayout());
JPanel game = new VirusGamePanel();
JPanel start = new StartScreen();
public Virus(){
jf.setResizable(false);
jf.setSize(600,600);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(EXIT_ON_CLOSE);
jf.setVisible(true);
jf.add(thegame);
thegame.add(start);
thegame.add(game);
}
public static void main(String[] args) {
new Virus();
}
}
You simply have to right this in your actionPerformed(...)
method :
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==start)
{
//what to do here?
CardLayout cardLayout = (CardLayout) Virus.thegame.getLayout();
cardLayout.next(Virus.thegame);
}
}
As very much pointed out by @kleopatra (THE EMPRESS) herself, don't override paint()
instead do your painting stuff inside paintComponent(Graphics g)
method of any JPanel/JComponent
. Moreover, first add the components to your JFrame
, once it's size is realized, then only set it to Visible, not before that. Instead of setting sizes for the JFrame
simply override the JPanel
's method getPreferredSize()
, make it return some valid Dimension
Object.
Do watch this sequence, as you write your code the next time :
public Virus(){
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setResizable(false);
thegame.add(start);
thegame.add(game);
jf.add(thegame);
jf.pack();
jf.setLocationRelativeTo(null);
jf.setVisible(true);
}
Here is your full code :
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.CardLayout;
public class Virus extends JFrame{
private static final long serialVersionUID =1L;
JFrame jf = new JFrame("Virus");
static JPanel thegame = new JPanel(new CardLayout());
JPanel game = new VirusGamePanel();
JPanel start = new StartScreen();
public Virus(){
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setResizable(false);
thegame.add(start);
thegame.add(game);
jf.add(thegame);
jf.pack();
jf.setLocationRelativeTo(null);
jf.setVisible(true);
}
public static void main(String[] args) {
new Virus();
}
}
class StartScreen extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
JButton start = new JButton("Start");
public StartScreen(){
start.addActionListener(this);
start.setBounds(new Rectangle(400,300,100,30));
this.add(start);
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setFont(new Font("Impact",Font.BOLD,72));
g.setColor(Color.MAGENTA);
g.drawString("Virus",275,300);
}
@Override
public Dimension getPreferredSize()
{
return (new Dimension(600, 600));
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==start)
{
//what to do here?
CardLayout cardLayout = (CardLayout) Virus.thegame.getLayout();
cardLayout.next(Virus.thegame);
}
}
}
class VirusGamePanel extends JPanel
{
public VirusGamePanel()
{
JLabel label = new JLabel("I am ON", JLabel.CENTER);
add(label);
}
@Override
public Dimension getPreferredSize()
{
return (new Dimension(600, 600));
}
}
Your StartScreen
class has to have access to the instance of the CardLayout
of the JFrame
and the instance of the VirusGamePanel
class. You can pass these instances in the constructor or a setLayout
method and setVirusGamePanel
method of your StartScreen
class.
Something like:
layout.next(virusGamePanel);
should work.