Adding JPAnels from Other Classes to the Cardlayout

Adding JPanels from other classes to the cardLayout

I had made a small program, hopefully the comments written in the program, might be able to guide you, to understand how to use CardLayout.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/* Here we are first declaring our class that will act as the
* base for other panels or in other terms the base for CardLayout.
*/

public class CardLayoutTest
{
private static final String CARD_JBUTTON = "Card JButton";
private static final String CARD_JTEXTFIELD = "Card JTextField";
private static final String CARD_JRADIOBUTTON = "Card JRadioButton";

private static void createAndShowGUI()
{
JFrame frame = new JFrame("Card Layout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);

// This JPanel is the base for CardLayout for other JPanels.
final JPanel contentPane = new JPanel();
contentPane.setLayout(new CardLayout(20, 20));

/* Here we be making objects of the Window Series classes
* so that, each one of them can be added to the JPanel
* having CardLayout.
*/
Window1 win1 = new Window1();
contentPane.add(win1, CARD_JBUTTON);
Window2 win2 = new Window2();
contentPane.add(win2, CARD_JTEXTFIELD);
Window3 win3 = new Window3();
contentPane.add(win3, CARD_JRADIOBUTTON);

/* We need two JButtons to go to the next Card
* or come back to the previous Card, as and when
* desired by the User.
*/
JPanel buttonPanel = new JPanel();
final JButton previousButton = new JButton("PREVIOUS");
previousButton.setBackground(Color.BLACK);
previousButton.setForeground(Color.WHITE);
final JButton nextButton = new JButton("NEXT");
nextButton.setBackground(Color.RED);
nextButton.setForeground(Color.WHITE);
buttonPanel.add(previousButton);
buttonPanel.add(nextButton);

/* Adding the ActionListeners to the JButton,
* so that the user can see the next Card or
* come back to the previous Card, as desired.
*/
previousButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
CardLayout cardLayout = (CardLayout) contentPane.getLayout();
cardLayout.previous(contentPane);
}
});
nextButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
CardLayout cardLayout = (CardLayout) contentPane.getLayout();
cardLayout.next(contentPane);
}
});

// Adding the contentPane (JPanel) and buttonPanel to JFrame.
frame.add(contentPane, BorderLayout.CENTER);
frame.add(buttonPanel, BorderLayout.PAGE_END);

frame.pack();
frame.setVisible(true);
}

public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}

class Window1 extends JPanel
{
/*
* Here this is our first Card of CardLayout, which will
* be added to the contentPane object of JPanel, which
* has the LayoutManager set to CardLayout.
* This card consists of Two JButtons.
*/
private ActionListener action;

public Window1()
{
init();
}

private void init()
{
final JButton clickButton = new JButton("CLICK ME");
final JButton dontClickButton = new JButton("DON\'T CLICK ME");

action = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
if (ae.getSource() == clickButton)
{
JOptionPane.showMessageDialog(null, "Hello there dude!"
, "Right Button", JOptionPane.INFORMATION_MESSAGE);
}
else if (ae.getSource() == dontClickButton)
{
JOptionPane.showMessageDialog(null, "I told you not to click me!"
, "Wrong Button", JOptionPane.PLAIN_MESSAGE);
}
}
};

clickButton.addActionListener(action);
dontClickButton.addActionListener(action);

add(clickButton);
add(dontClickButton);
}
}

class Window2 extends JPanel implements ActionListener
{
/*
* Here this is our second Card of CardLayout, which will
* be added to the contentPane object of JPanel, which
* has the LayoutManager set to CardLayout.
* This card consists of a JLabel and a JTextField
* with GridLayout.
*/

private JTextField textField;

public Window2()
{
init();
}

private void init()
{
setLayout(new GridLayout(1, 2));
JLabel userLabel = new JLabel("Your Name : ");
textField = new JTextField();
textField.addActionListener(this);

add(userLabel);
add(textField);
}

public void actionPerformed(ActionEvent e)
{
if (textField.getDocument().getLength() > 0)
JOptionPane.showMessageDialog(null, "Your Name is : " + textField.getText()
, "User\'s Name : ", JOptionPane.QUESTION_MESSAGE);
}
}

class Window3 extends JPanel
{
/*
* Here this is our third Card of CardLayout, which will
* be added to the contentPane object of JPanel, which
* has the LayoutManager set to CardLayout.
* This card consists of Two JLabels and two JCheckBox
* with GridLayout.
*/
private ActionListener state;

public Window3()
{
init();
}

public void init()
{
setLayout(new GridLayout(2, 2));
JLabel maleLabel = new JLabel("MALE", JLabel.CENTER);
final JCheckBox maleBox = new JCheckBox();
JLabel femaleLabel = new JLabel("FEMALE", JLabel.CENTER);
final JCheckBox femaleBox = new JCheckBox();

state = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
if (maleBox == (JCheckBox) ae.getSource())
{
femaleBox.setSelected(false);
JOptionPane.showMessageDialog(null, "Congrats you are a Male"
, "Gender : ", JOptionPane.INFORMATION_MESSAGE);
}
else if (femaleBox == (JCheckBox) ae.getSource())
{
maleBox.setSelected(false);
JOptionPane.showMessageDialog(null, "Congrats you are a Female"
, "Gender : ", JOptionPane.INFORMATION_MESSAGE);
}
}
};

maleBox.addActionListener(state);
femaleBox.addActionListener(state);
add(maleLabel);
add(maleBox);
add(femaleLabel);
add(femaleBox);
}
}

CardLayout changing panel from another class

Make the CardLayout and the CardLayout-using JPanel private fields of the CardLayout-using class, for instance called cardLayout and cardShowingPanel, and give your that class two public methods:

public void nextCard() {
// in here call next() on the CardLayout
cardLayout.next(cardShowingPanel);
}

and

public void previousCard() {
// in here call previous() on the CardLayout
cardLayout.previous(cardShowingPanel);
}

and for ultimate flexibility, consider also creating a showCard(...) method that mirrors the show(...) method of the CardLayout:

public void showCard(String key) {
cardLayout.show(cardShowingPanel, key);
}

When I've done this, I've used public constants for the keys to add components to the card-showing JPanel, so that outside classes can re-use these constants when they want to display a particular card.

Then any class that holds a reference to this class can call the public methods and swap cards.


For example, to use the code above:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CardLayoutTestPanel extends JPanel {
public static final String CARD_JBUTTON = "Card JButton";
public static final String CARD_JTEXTFIELD = "Card JTextField";
public static final String CARD_JRADIOBUTTON = "Card JRadioButton";

private static void createAndShowGui() {
final CardLayoutTestPanel cardLayoutTestPanel = new CardLayoutTestPanel();

JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 5));
buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JButton previousButton = new JButton("PREVIOUS");
previousButton.setBackground(Color.BLACK);
previousButton.setForeground(Color.WHITE);
final JButton nextButton = new JButton("NEXT");
nextButton.setBackground(Color.RED);
nextButton.setForeground(Color.WHITE);
buttonPanel.add(previousButton);
buttonPanel.add(nextButton);

previousButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
cardLayoutTestPanel.previousCard();
}
});
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
cardLayoutTestPanel.nextCard();
}
});

JFrame frame = new JFrame("CardLayoutTest");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(cardLayoutTestPanel);
frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

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

private CardLayout cardLayout = new CardLayout(20, 20);
private JPanel cardShowingPanel = new JPanel(cardLayout);

public CardLayoutTestPanel() {
/*
* Here we be making objects of the Window Series classes so that, each
* one of them can be added to the JPanel having CardLayout.
*/
Window1 win1 = new Window1();
cardShowingPanel.add(win1, CARD_JBUTTON);
Window2 win2 = new Window2();
cardShowingPanel.add(win2, CARD_JTEXTFIELD);
Window3 win3 = new Window3();
cardShowingPanel.add(win3, CARD_JRADIOBUTTON);

setLayout(new BorderLayout());

// Adding the contentPane (JPanel) and buttonPanel to JFrame.
add(cardShowingPanel, BorderLayout.CENTER);
}

public void nextCard() {
cardLayout.next(cardShowingPanel);
}

public void previousCard() {
cardLayout.previous(cardShowingPanel);
}

public void showCard(String key) {
cardLayout.show(cardShowingPanel, key);
}

}

class Window1 extends JPanel {
/*
* Here this is our first Card of CardLayout, which will be added to the
* contentPane object of JPanel, which has the LayoutManager set to
* CardLayout. This card consists of Two JButtons.
*/
private ActionListener action;

public Window1() {
init();
}

private void init() {
final JButton clickButton = new JButton("CLICK ME");
final JButton dontClickButton = new JButton("DON\'T CLICK ME");

action = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == clickButton) {
JOptionPane.showMessageDialog(null, "Hello there dude!",
"Right Button", JOptionPane.INFORMATION_MESSAGE);
} else if (ae.getSource() == dontClickButton) {
JOptionPane.showMessageDialog(null,
"I told you not to click me!", "Wrong Button",
JOptionPane.PLAIN_MESSAGE);
}
}
};

clickButton.addActionListener(action);
dontClickButton.addActionListener(action);

add(clickButton);
add(dontClickButton);
}
}

class Window2 extends JPanel implements ActionListener {
/*
* Here this is our second Card of CardLayout, which will be added to the
* contentPane object of JPanel, which has the LayoutManager set to
* CardLayout. This card consists of a JLabel and a JTextField with
* GridLayout.
*/

private JTextField textField;

public Window2() {
init();
}

private void init() {
setLayout(new GridLayout(1, 2));
JLabel userLabel = new JLabel("Your Name : ");
textField = new JTextField();
textField.addActionListener(this);

add(userLabel);
add(textField);
}

public void actionPerformed(ActionEvent e) {
if (textField.getDocument().getLength() > 0)
JOptionPane.showMessageDialog(null,
"Your Name is : " + textField.getText(), "User\'s Name : ",
JOptionPane.QUESTION_MESSAGE);
}
}

class Window3 extends JPanel {
/*
* Here this is our third Card of CardLayout, which will be added to the
* contentPane object of JPanel, which has the LayoutManager set to
* CardLayout. This card consists of Two JLabels and two JCheckBox with
* GridLayout.
*/
private ActionListener state;

public Window3() {
init();
}

public void init() {
setLayout(new GridLayout(2, 2));
JLabel maleLabel = new JLabel("MALE", JLabel.CENTER);
final JCheckBox maleBox = new JCheckBox();
JLabel femaleLabel = new JLabel("FEMALE", JLabel.CENTER);
final JCheckBox femaleBox = new JCheckBox();

state = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (maleBox == (JCheckBox) ae.getSource()) {
femaleBox.setSelected(false);
JOptionPane.showMessageDialog(null, "Congrats you are a Male",
"Gender : ", JOptionPane.INFORMATION_MESSAGE);
} else if (femaleBox == (JCheckBox) ae.getSource()) {
maleBox.setSelected(false);
JOptionPane.showMessageDialog(null, "Congrats you are a Female",
"Gender : ", JOptionPane.INFORMATION_MESSAGE);
}
}
};

maleBox.addActionListener(state);
femaleBox.addActionListener(state);
add(maleLabel);
add(maleBox);
add(femaleLabel);
add(femaleBox);
}
}

how to show panels of other classes in cardlayout?

I just answered a question which might as well have the same answer as this. Changing panels in gui I think this will also help you too. There is class Card which you extend to allow for more card types. I have made two card types for this example.

imports

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.Vector;

main class

public class Gui extends JFrame implements ListSelectionListener {

Vector<String> menuList = new Vector<>();
JList<String> menu = new JList<>(menuList);

JPanel content = new JPanel(new CardLayout());

Gui(){
//put menu on left, content in middle
add(menu, BorderLayout.WEST);
add(content, BorderLayout.CENTER);
menu.addListSelectionListener(this);

//add multiple cards
addCard(new SimpleLabelCard("First Item", "First Item Text"));
addCard(new SimpleLabelCard("Second Item", "Second Item Text"));
addCard(new SimpleTextAreaCard("Third Item", "Third Item Text"));

//set content to first item
((CardLayout) content.getLayout()).show(content, "First Item");
}

private void addCard(Card c){
menuList.add(c.name);
content.add(c, c.name);
}

public static void main(String [] args){
Gui gui = new Gui();
gui.setSize(600, 500);
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setVisible(true);
}

@Override
public void valueChanged(ListSelectionEvent e) {
if(e.getValueIsAdjusting()) return;

//set card layout from JList menu
((CardLayout) content.getLayout()).show(content, menu.getSelectedValue());
}
}

other classes, put each one in their respective file.

//Card.java
//this is the basic card class the extends JPanel
//it contains the name so you can easily switch to it
public class Card extends JPanel{
public final String name;

public Card(String name){
this.name = name;
}
}

//SimpleLabelCard.java
//extends Card, so it is also a JPanel
public class SimpleLabelCard extends Card{

private JLabel label = new JLabel();

public SimpleLabelCard(String name, String text) {
super(name);
label.setText(text);
add(label);
}
}

//SimpleTextAreaCard.java
public class SimpleTextAreaCard extends Card{

private JTextArea text = new JTextArea();

public SimpleTextAreaCard(String name, String text) {
super(name);
this.text.setText(text);
setLayout(new BorderLayout());
add(this.text, BorderLayout.CENTER);
}
}

now if you want to make another type of card just extend the card class. I hope this is straight forward enough. It was actually a learning experience for me.

Card Layout with different classes

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

Using JButton in one class to change card in another class (using CardLayout)

You can create a class in between to orchestrate the whole switching, to prevent sharing lots of instances between classes. I have created an example using a CardSwitcher that does exactly that.

Let me know if you found it useful.

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Test extends JPanel {

public static void main(String[] args) {
JFrame frame = new JFrame("Test");

Test tst = new Test();
frame.getContentPane().add(tst);

frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);

}

public Test() {
setLayout(new BorderLayout());
CardLayout cardLayout = new CardLayout();

JPanel centerPanel = new JPanel(cardLayout);

JPanel panelA = new JPanel();
panelA.add(new JLabel("Panel A"));
centerPanel.add(panelA, "A");
JPanel panelB = new JPanel();
panelB.add(new JLabel("Panel B"));
centerPanel.add(panelB, "B");
JPanel panelC = new JPanel();
panelC.add(new JLabel("Panel C"));
centerPanel.add(panelC, "C");

CardSwitcher switcher = new CardSwitcher(centerPanel, cardLayout);
ButtonPanel buttons = new ButtonPanel(switcher);

add(centerPanel, BorderLayout.CENTER);
add(buttons, BorderLayout.SOUTH);

}

class ButtonPanel extends JPanel {
public ButtonPanel(CardSwitcher switcher) {
setLayout(new FlowLayout());

JButton buttonA = new JButton("Show A");
buttonA.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
switcher.switchTo("A");
}
});
add(buttonA);

JButton buttonB = new JButton("Show B");
buttonB.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
switcher.switchTo("B");
}
});
add(buttonB);

JButton buttonC = new JButton("Show C");
buttonC.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
switcher.switchTo("C");
}
});
add(buttonC);

}
}

class CardSwitcher {
CardLayout layout;
Container container;

public CardSwitcher(Container container, CardLayout layout) {
this.layout = layout;
this.container = container;
}

public void switchTo(String card) {
layout.show(container, card);
}
}
}


Related Topics



Leave a reply



Submit