3

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

}
gadu
  • 1,816
  • 1
  • 17
  • 31

1 Answers1

3

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();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Added the JLetterField class - also where am I trying to add the contentPane back onto itself, whhere i say frame.add(master, BorderLayout.CENTER) ? i'm trying to make it so that on opening the only two buttons you can see are the "info" button that says "Help" and changes the layout to show the "Instructions.png" picture - and then under that button a button labeled "Play" (which I haven't made yet) that will change the layout to the "GAME" card.. – gadu Apr 23 '13 at 22:05
  • 1
    @user2310306: rather than give us this class, for the forum purposes, you should just use a JTextField. The class has nothing to do with your problem at hand, so your job is to simplify your code so that it still compiles but shows your problem. Please do this now. Regarding the contentPane, the master JPanel *is* the JFrame's contentPane. Again, why are you trying to add it back? Makes no sense. It's already there! I suggest that you scrap the above code, and just try to solve the problem at hand with the simplest code possible. – Hovercraft Full Of Eels Apr 23 '13 at 22:07
  • editted.. thanks I'm very new to java and this website thanks for being patient – gadu Apr 23 '13 at 22:11
  • 1
    @user2310306: please see 2nd edit to answer for sample code. Please read the CardLayout tutorial as well. – Hovercraft Full Of Eels Apr 23 '13 at 22:30