Question

I've been trying to figure out CardLayout with action listeners on button (so like - starts on a load-up page- and on a button click switches to a different "card"

my code won't even run right now i'm not entirely sure why - most implementations I can find use ItemListeners and Combo Boxes

The basic process I've done is create a master JPanel, but my cards JPanel onto the master JPanel, but my different cards into the cards JPanel, then add the master JPanel to the frame to display...

Also, for one of my cards I only need to display a picture - I previously implemented this by just creating a new pop-up window but It would be nice to be able to switch the frame to show it... I don't know why I can't figure this out

Here's my code:

import java.awt.*;

/** 
 * Game
 * Main class that specifies the frame and widgets of the GUI
 */
public class Game implements Runnable {
public void run(){

    final String ON_OPEN = "Welcome!"; //Opening frame
    final String GAME = "Play!"; // Game Frame
    final String STATS = "Stats"; // Post-Game Stat Frame
    final String HELP = "Help"; //tutorial frame
    JPanel cards = new JPanel(); 
    JPanel master; // a panel for the card layout

    final JFrame frame = new JFrame(ON_OPEN);
    frame.setLocation(500,200);

    //Create the master layout for the program
    master = (JPanel) frame.getContentPane();
    master.setLayout(new BorderLayout()); // creating master layout

    //Create panel for all the cards in CardLayout
    final CardLayout cLay = new CardLayout();
    cards.setLayout(cLay);


    // all the cards
    final JPanel help = new JPanel();
    final JPanel stats = new JPanel();
    final JPanel game = new JPanel (new BorderLayout());
    final JPanel open = new JPanel (new FlowLayout());


    // setting up ON_OPEN layout - uses JPanel open

    final ImageIcon img = new ImageIcon("Instructions.png", "My Instructions..."); // the image I want shown under HELP card
    final JButton info = new JButton("Help");
    info.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
    //      cLay.show(help, HELP);     // WHAT I NORMALLY SHOULD BE DOING, RATHER JUST MAKE A NEW FRAME FOR THIS THOUGH
    //      frame.pack();

            final JFrame infoFrame = new JFrame("Tutorial");
            infoFrame.setLocation(500,50);
            JLabel tutorialImg = new JLabel(img);
    //      int w = img.getIconWidth();
        //  int h = img.getIconHeight();
            //infoFrame.setSize(w, h);
            infoFrame.pack();
            infoFrame.add(tutorialImg);
            infoFrame.setVisible(true);
        }
    });
    open.add(info); // the open-tutorial button



    //Add them to the cards JPanel
    cards.add(open, ON_OPEN);
    cards.add(help, HELP);
    cards.add(stats, STATS);
    cards.add(game, GAME);

    //Add the cards panel to the Master layout panel
    master.add(cards);


    // This code is all commented out because I'm not sure what I'm doing here...
//  frame.add(cards);
//  cLay.show(cards, ON_OPEN);

//  frame.add(open, BorderLayout.CENTER);

    // Main playing area - I want this to be shown in the GAME card...

    GridLayout tileGrid = new GridLayout(4,4);
    final JPanel grid = new JPanel(tileGrid);
      //    game.add(grid, BorderLayout.CENTER);

    //      grid.setLayout(tileGrid);
    //  frame.add(grid, BorderLayout.CENTER);


    // Input - holds typing box
    //        final JPanel status_panel = new JPanel();

    //  frame.add(cards, BorderLayout.CENTER);


//  frame.add(open, BorderLayout.CENTER);

    final JTextField typingArea = new JTextField();
    typingArea.setFocusTraversalKeysEnabled(false);
    typingArea.setEditable(true);
    typingArea.setFocusable(true);
    typingArea.requestFocus();


    frame.add(typingArea, BorderLayout.SOUTH);
    typingArea.addKeyListener(new KeyAdapter() {
        public void keyPressed (KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_ENTER) { // enter key is pressed
                String userWord = typingArea.getText().toLowerCase();
                typingArea.setText("");

            }
        }
    });


    final JLabel status = new JLabel("Running...");
    //        status_panel.add(status);

    // Reset button
    final JPanel control_panel = new JPanel();
    frame.add(control_panel, BorderLayout.NORTH);



    ]

    // Put the frame on the screen
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}


public static void main(String[] args){
    SwingUtilities.invokeLater(new Game());
}

}
Was it helpful?

Solution

Problems:

  • Your code doesn't compile for us since we don't have the JLetterField class.
  • You're trying to add the JFrame's contentPane back on itself, and causes an exception and doesn't make sense.

Edit 1:

  • Your latest code shows you putting everything into one very large run() method but in doing so, you loose much and gain nothing.
  • I suggest getting rid of the Runnable interface, there's no need for it, and creating a true OOP compliant class, one with private fields and public and private methods.
  • Your actionPerformed method shows no attempt at changing the CardLayout's displayed card.
  • I suggest that you get rid of the code to show a new window and try to place card swapping code there.
  • Make your CardLayout and the card-displaying JPanel fields of the class so that other methods can access them and call their methods.

Edit 2:

For example the following code shows the swapping of cards using 3 JButtons. One to get the previous card, one to get the next card, and one to show how to get a specific card (here the 2nd):

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class CardLayoutEg extends JPanel {
   private static final String[] CARD_LABELS = { "one", "two", "three", "four",
         "five", "six", "seven", "eight", "nine", "ten" };
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private CardLayout cardlayout = new CardLayout();
   private JPanel cardHolder = new JPanel(cardlayout);
   private Action[] actions = { new ShowPreviousAction(), new ShowNextAction(),
         new ShowTwoCardAction() };

   public CardLayoutEg() {
      for (String cardLabelText : CARD_LABELS) {
         JLabel cardLabel = new JLabel(cardLabelText, SwingConstants.CENTER);
         cardHolder.add(cardLabel, cardLabelText);
      }

      JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
      for (Action action : actions) {
         btnPanel.add(new JButton(action));
      }

      setLayout(new BorderLayout());
      add(cardHolder, BorderLayout.CENTER);
      add(btnPanel, BorderLayout.SOUTH);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private class ShowPreviousAction extends AbstractAction {
      public ShowPreviousAction() {
         super("Previous");
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         cardlayout.previous(cardHolder);
      }
   }

   private class ShowNextAction extends AbstractAction {
      public ShowNextAction() {
         super("Next");
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         cardlayout.next(cardHolder);
      }
   }

   private class ShowTwoCardAction extends AbstractAction {
      public ShowTwoCardAction() {
         super("Show Two");
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         cardlayout.show(cardHolder, CARD_LABELS[1]);
      }
   }

   private static void createAndShowGui() {
      CardLayoutEg mainPanel = new CardLayoutEg();

      JFrame frame = new JFrame("CardLayout Example");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top