Swing CardLayout Runtime Error
-
20-12-2019 - |
Question
This program is supposed to add two panels to a JFrame, each with a switch button allowing the user to switch between each panel. It compiles fine, but when I try to click the switch1 button, I get this error:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.awt.BorderLayout cannot be cast to java.awt.CardLayout at tester.actionPerformed(tester.java:36) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.setPressed(Unknown Source) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$200(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)
I already did set the JFrame layout to CardLayout so when I use this.getLayout(), it should return a CardLayout object. This is the program:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class tester extends JFrame implements ActionListener
{
CardLayout cc = new CardLayout();
JLabel text1 = new JLabel("Panel 1");
JLabel text2 = new JLabel("Panel 2");
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JButton switch1 = new JButton("Switch1");
JButton switch2 = new JButton("Switch2");
boolean panel = true;
public tester()
{
setSize(100, 100);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(cc);
switch1.addActionListener(this);
switch2.addActionListener(this);
panel1.add(switch1);
panel1.add(text1);
panel2.add(switch2);
panel2.add(text2);
add(panel1, "Panel 1");
add(panel2, "Panel 2");
setVisible(true);
}
public void actionPerformed(ActionEvent evt)
{
if(panel)
{
CardLayout pane = (CardLayout)this.getLayout();
pane.last(this);
panel = false;
}
else
{
CardLayout pane = (CardLayout)this.getLayout();
pane.first(this);
panel = true;
}
repaint();
}
public static void main(String[] args)
{
tester test = new tester();
}
}
Solution
The quick fix is to reference the CardLayout
and content pane directly. Viz.
public void actionPerformed(ActionEvent evt)
{
if(panel)
{
//CardLayout pane = (CardLayout)this.getLayout();
cc.last(this.getContentPane());
panel = false;
}
else
{
//CardLayout pane = (CardLayout)this.getLayout();
cc.first(this.getContentPane());
panel = true;
}
//repaint(); not necessary either..
}
A better fix is to design the GUI in a JPanel
(and use the CardLayout
in that), and to simply create an instance of JFrame
in which to show the panel (instead of extending frame).