CardLayout in Java change by action in one of the 'cards'

2d-games, cardlayout, java, jpanel, swing

Solution

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));
    }
}

Problem

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(); } } ```

Original source