Hot questions for Using Applets in cardlayout

Question:

My JPanel startPan is supposed to display when the applet starts but right now, only the JButton setupGameBut displays. But if I click setupGameBut and then cancelBut to return to startPan, it displays the rules but still doesn't display the JLabel headingLab (which does show up on setupPan).

As well as that, it displays components from other panels behind the panel currently being shown but they're unable to be interacted with.

And on clicking a button, if you move the cursor away from it before it loads the next card, it won't update to the button supposed to be shown there until you mouse-over again. I've a feeling that I'm doing something fundamentally wrong with my code that I have these problems but I'm not sure.

/*
*Java Version:      1.8.0_25
*Author:            Peadar Ó Duinnín
*Student Number:    R00095488
*/

package As1;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Choice;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class AUIApplet extends JApplet {
    private final int APPLET_WIDTH;
    private final int APPLET_HEIGHT;
    private final int[] highScores = new int[3];
    private int currentScore;

    final Font normalFont = new Font("Cambria", Font.PLAIN, 18);
    final Font headingFont = new Font("Cambria", Font.BOLD, 24);
    JPanel contPan, startPan, setupPan, gamePan, scorePan, startInfoPan, gameInfoPan, rulePan, setupInfoPan, gameOptPan;
    JButton setupGameBut, cancelBut, endGameBut, startGameBut;
    JLabel highScoreLab, currentScoreLab, headingLab, rulesLab, difficultyScoreLab;
    Choice difficulty;
    CardLayout cl = new CardLayout();

    public AUIApplet() {
        this.APPLET_HEIGHT = 400;
        this.APPLET_WIDTH = 600;
        for (int i : highScores) {
            i = 0;
        }
    }

    @Override
    public void init() {
        //set applet size
        setSize(APPLET_WIDTH, APPLET_HEIGHT);

        //start screen
        startPan = new JPanel();
        startPan.setLayout(new BorderLayout());

        //setup screen
        setupPan = new JPanel();
        setupPan.setLayout(new BorderLayout());

        setupGameBut = new JButton("New Game");
        cancelBut = new JButton("Cancel");

        //game screen
        gamePan = new JPanel();
        gamePan.setLayout(new BorderLayout());

        endGameBut = new JButton("Quit Game");

        //heading label
        headingLab = new JLabel("Number Memory");
        headingLab.setFont(headingFont);

        //rule panel
        rulePan = new JPanel();
        rulePan.setLayout(new GridLayout(8,1));
        rulePan.add(new JLabel("Rules:"));
        rulePan.add(new JLabel("1. You will be shown a series of numbers, one at a time."));
        rulePan.add(new JLabel("2. You must recite the series of numbers after the last number has been displayed."));
        rulePan.add(new JLabel("3. After each correct recitation of the sequence, another sequence will play with one extra number."));
        rulePan.add(new JLabel("Note: You can decrease/increase the time each number displays for by changing the difficulty."));

        //difficulty selection
        difficulty = new Choice();
        difficulty.add("Easy");
        difficulty.add("Normal");
        difficulty.add("Hard");
        difficulty.add("Extra Hard");
        difficulty.select(1);

        difficultyScoreLab = new JLabel("" + highScores[1] + "");

        switch(difficulty.getSelectedIndex()) {
            case 0: difficultyScoreLab.setText("" + highScores[0] + "");
                break;
            case 1: difficultyScoreLab.setText("" + highScores[1] + "");
                break;
            case 2: difficultyScoreLab.setText("" + highScores[2] + "");
                break;
            case 3: difficultyScoreLab.setText("" + highScores[3] + "");
                break;
        }

        //game option panel
        gameOptPan = new JPanel();
        gameOptPan.setLayout(new GridLayout(1,2));
        startGameBut = new JButton("Start Game");
        gameOptPan.add(startGameBut);
        gameOptPan.add(difficulty);

        //start info panel
        startInfoPan = new JPanel();
        startInfoPan.setLayout(new BorderLayout());
        startInfoPan.add(rulePan, BorderLayout.CENTER);

        //setup info panel
        setupInfoPan = new JPanel();
        setupInfoPan.setLayout(new BorderLayout());
        setupInfoPan.add(gameOptPan, BorderLayout.SOUTH);
        setupInfoPan.add(new JLabel("High Score:"), BorderLayout.NORTH);
        setupInfoPan.add(difficultyScoreLab, BorderLayout.CENTER);

        //game info panel
        gameInfoPan = new JPanel();
        gameInfoPan.setLayout(new BorderLayout());

        //score panel
        scorePan = new JPanel();
        scorePan.setLayout(new GridLayout(10,1));
        highScoreLab = new JLabel("High Score: " + highScores[difficulty.getSelectedIndex()] + "  ");
        currentScoreLab = new JLabel("Current Score: " + currentScore + "  ");
        scorePan.add(highScoreLab);
        scorePan.add(currentScoreLab);

        //adding to start panel
        startPan.add(setupGameBut, BorderLayout.SOUTH);
        startPan.add(headingLab, BorderLayout.NORTH);
        startPan.add(startInfoPan, BorderLayout.CENTER);

        //adding to setup panel
        setupPan.add(cancelBut, BorderLayout.SOUTH);
        setupPan.add(headingLab, BorderLayout.NORTH);
        setupPan.add(setupInfoPan, BorderLayout.CENTER);

        //adding to game panel
        gamePan.add(endGameBut, BorderLayout.SOUTH);
        gamePan.add(headingLab, BorderLayout.NORTH);
        gamePan.add(gameInfoPan, BorderLayout.CENTER);
        gamePan.add(scorePan, BorderLayout.EAST);

        //setting up container panel and adding each screen to it
        contPan = new JPanel();
        contPan.setLayout(cl);
        contPan.add(startPan, "Start Applet Screen");
        contPan.add(setupPan, "Setup Game Screen");
        contPan.add(gamePan, "New Game Screen");

        //action listeners
        setupGameBut.addActionListener((ActionEvent e) -> {
            newGame();
        });

        startGameBut.addActionListener((ActionEvent e) -> {
            startGame();
        });

        cancelBut.addActionListener((ActionEvent e) -> {
            quitGame();
        });

        endGameBut.addActionListener((ActionEvent e) -> {
            quitGame();
        });

        //add container panel
        this.add(contPan);
    }

    @Override
    public void paint(Graphics g) {

    }

    public void newGame() {
        cl.show(contPan, "Setup Game Screen");
    }

    public void startGame() {
        cl.show(contPan, "New Game Screen");
    }

    public void quitGame() {
        cl.show(contPan, "Start Applet Screen");
        if (currentScore > highScores[difficulty.getSelectedIndex()]) {
            highScores[difficulty.getSelectedIndex()] = currentScore;
        }
        currentScore = 0;
    }

    @Override
    public Insets getInsets() {
        return new Insets(10, 10, 10, 10);
    }
}

Answer:

Don't override paint().

There is rarely ever a reason to do this and I can't think of any reason for having an empty method. An empty method is bound to cause problems

I'm using it later in my program for painting stuff

Still don't override paint(). Custom painting is done by overriding the paintComponent(...) method of a JPanel (or JComponent) and then you add the panel to the applet.

Read the section from the Swing tutorial on Custom Painting for more information and examples.

Question:

I'm having trouble with this JApplet. At the moment I have a CardLayout JPanel which contains two BorderLayout JPanels. Whenever I run it, the components added to each 'card' (a JButton to go back to the other JPanel) don't display unless I use setVisible(true) for each LayoutManager. Furthermore, none of my ActionListeners work. I'm assuming because they only use show() and there's something else I have to do that's alluding me.

Must I use setVisible(true)? It seems from other questions that there's a way of doing this without that. Here's the code I'm having trouble with:

/*
*Java Version:      1.8.0_25
*Author:            Peadar Ó Duinnín
*Student Number:    R00095488
*/

package As1;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class AUIJApplet extends JApplet implements ActionListener {
    private final int WIDTH = 600;
    private final int HEIGHT = 400;
    private int highScore;
    private int currentScore;

    JPanel panelCont = new JPanel();
    JPanel startPanel = new JPanel();
    JPanel gamePanel = new JPanel();
    JButton newGameButton = new JButton("New Game");
    JButton endGameButton = new JButton("End Game");
    JLabel highScoreLabel;
    JLabel currentScoreLabel;
    CardLayout cl = new CardLayout();
    BorderLayout bl = new BorderLayout();

    public AUIJApplet() {
        highScore = 0;
    }

    @Override
    public void init() {
        setSize(WIDTH, HEIGHT);

        panelCont.setLayout(cl);
        startPanel.setLayout(bl);
        gamePanel.setLayout(bl);

        startPanel.add(newGameButton, BorderLayout.SOUTH);
        gamePanel.add(endGameButton, BorderLayout.SOUTH);
        startPanel.setBackground(Color.BLUE);
        gamePanel.setBackground(Color.GREEN);

        panelCont.add(startPanel, "Start Applet Screen");
        panelCont.add(gamePanel, "New Game Screen");

        newGameButton.addActionListener((e) -> {
            newGame();
        });

        endGameButton.addActionListener((e) -> {
            quitGame();
        });

        cl.show(panelCont, "Start Applet Screen");
        this.add(panelCont);
    }

    public void newGame() {
        cl.show(panelCont, "New Game Screen");
        showScores(gamePanel);
    }

    public void quitGame() {
        cl.show(panelCont, "Start Applet Screen");
        if (currentScore > highScore) {
            highScore = currentScore;
        }
        currentScore = 0;
    }

    public void showScores(JPanel currentPanel) {
        currentPanel.add(new JLabel("High Score:") , BorderLayout.EAST);
        currentPanel.add(highScoreLabel, BorderLayout.EAST);
        currentPanel.add(new JLabel("Current Score:"), BorderLayout.EAST);
        currentPanel.add(currentScoreLabel, BorderLayout.EAST);
    }

    @Override
    public void actionPerformed(ActionEvent ae) {

    }
}

Answer:

I have made the a little similar code to perform same operation it works for me try to write the code from scratch. Here is my code.

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.JApplet;
import javax.swing.*;


    public class Example extends JApplet {

        JPanel panel1,panel2,mainPanel;
        JButton start,stop;
        CardLayout cl = new CardLayout();
        @Override
        public void init() {
            panel1 = new JPanel();
            panel1.setBackground(Color.red);
            panel1.setLayout(new BorderLayout());
            panel2 = new JPanel();
            panel2.setBackground(Color.blue);
            panel2.setLayout(new BorderLayout());
            start = new JButton("Start");
            stop = new JButton("stop");
            panel1.add(start,BorderLayout.SOUTH);
            panel2.add(stop,BorderLayout.SOUTH);
            mainPanel = new JPanel();
            mainPanel.setLayout(cl);
            mainPanel.add(panel1,"First Panel");
            mainPanel.add(panel2, "Second Panel");
            start.addActionListener((ActionEvent e) -> {
                newGame();
            });
            stop.addActionListener((ActionEvent e) ->{
                endGame();
            });
            this.add(mainPanel);
        }

        public void newGame()
        {
            cl.show(mainPanel, "Second Panel");
        }
        public void endGame()
        {
            cl.show(mainPanel,"First Panel");
        }
    }

Question:

I need help with an applet that I am making for my coursework.

I am using card layout and I want the content of each card to be taken from different classes. Then in each card I want buttons to switch to other cards. I've seen examples that work in a similar way but they are based on JFrame rather than applet.

Please do not send me any external links, I've been researching card layout for several days already. I am a Java beginner and I am a slow learner. I would like someone to show me a basic example and explain how it is done. Thank you!

public class MainClass extends JApplet implements ActionListener {

        boolean inAnApplet = true;
        JButton btn1, btn2;
        JPanel cards;
        final static String PANEL1 = "";
        final static String PANEL2 = "";


        public MainClass() {

            Container contentPane = getContentPane();
            JPanel cbp = new JPanel();        
            cbp.add(new JLabel ("Hello world!"));

            contentPane.add(cbp, BorderLayout.NORTH);
            cards = new JPanel();
            cards.setLayout(new CardLayout());    


            JPanel p1 = new JPanel();
            p1.add(new JLabel("First panel!"));
            btn1 = new JButton("Text panel");
            btn1.addActionListener(this);
            p1.add(btn1);


            JPanel p2 = new JPanel();
            p2.add(new JLabel("Second panel!"));
            btn2 = new JButton("Button panel");
            btn2.addActionListener(this);
            p2.add(btn2);

            cards.add(p1, PANEL1);
            cards.add(p2, PANEL2);
            contentPane.add(cards, BorderLayout.CENTER);


        }

       public void init(){}

        public void actionPerformed(ActionEvent evt) {

            CardLayout cl = (CardLayout)(cards.getLayout());

                if(evt.getSource() == btn1)
                {
                    cl.show(cards, PANEL1);
                }
                else if(evt.getSource() == btn2)
                {
                    cl.show(cards, PANEL2);
                }   
           }
    }

Answer:

The code that I've given is literally taken from that tutorial.

So why don't your PANEL1 and PANEL2 variables have values? How do you expect it to work if you don't specify the name of the card??? How do you expect something to work if you don't copy working code? Why should we provide working code when you can't even follow the code from the tutorial? Why do you think any code we provide will be any different?

but I don't understand how to make each card a different class.

There is no difference. If you want to display a card you need to know the name of the card you want to display.

Right now you use:

JPanel p1 = new JPanel();
cards.add(p1, PANEL1);

So if the panel is in a different class then the code would be:

JPanel p1 = new SomeCustomPanel()
cards.add(p1, PANEL1);

If you want all the code in a separate panel then you will need to get the layout manager from the parent parent panel so the code in the ActionListener of each panel might be something like:

JPanel parent = childPanel.getParent();
CardLayout layout = (CardLayout)parent.getLayout();

Now you have access to the layout manager so you can switch cards assuming you know the name of each card. How you name each card and how you assign the card name is up to you.

Edit:

public class SomeCustomPanel extends JPanel
{
    public SomeCustomPanel
    {
        add( new JLabel("I'm a JLabel") );
        JButton button = new JButton("Switch Panel");
        add(button);
        button.addActionListener(...); // add ActionListener to swap cards
    }
}

Edit:

Well I used those names to try to show a parent/child relationship between comonents when you add components to a panel, or one panel to another panel.

When you use an ActionListener the source of the ActionEvent will be the JButton. So given the button that generated ActionEvent you can go back up the parent/child chain until you find the panel using the CardLayout.

So your code would be more like:

JButton button = (JButton)e.getSource();
JPanel someCustomPanel = (JPanel)button.getParent();
JPanel cardLayoutPanel = (JPanel)someCustomPanel.getParent();
CardLayout layout = (CardLayout)cardLayoutPanel.getLayout();
layout.show(cardLayoutPanel, "...");

Now that you have the layout manager you just need to know the name of the card you want to display