How to effectively use cardlayout in java in order to switch from panel using buttons inside various panel constructors
I am new to using cardlayout and I have a few questions on how to implement it. I first would like to know the best way to implement cardlayout so that I can switch from panel to panel. My main question is how to use buttons inside the constructors of my panels to switch from panel to panel. I just started working on this project today so you will see some code that is not finished or that does not make sense. I first tried to make all my classes to extend JFrame but that led to multiple unwanted windows. If I can get some sort of example on how to effectively use cardlayout and how to switch panels using the buttons within my other panel constructors. My attempts on using cardlayout only worked for buttons that I created in my gui class however that is not the result I want. Please help if you can and thanks in advance.
This is my main class.
public class controller{
public static void main(String[] args){
new Gui();
}
}
This is my gui class.
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class Gui extends JFrame{
homePage home = new homePage();
public JPanel loginPanel = new textEmailLog(),
registerPanel = new Register(),
homePanel = new homePage(), viewPanel = new emailView(),
loadPanel = new loadEmail(), contentPanel = new JPanel(new CardLayout());
CardLayout cardLayout = new CardLayout();
public Gui(){
super("Email Database Program");
setSize(700,700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPanel.setLayout(cardLayout);
contentPanel.add(loginPanel, "Login");
contentPanel.add(registerPanel, "Register");
contentPanel.add(homePanel, "Home");
contentPanel.add(viewPanel, "View");
contentPanel.add(loadPanel, "Load");
this.setContentPane(contentPanel);
cardLayout.show(contentPanel, "Login");
setVisible(true);
}
My Login Panel class
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
//panel has been added
public class textEmailLog extends JPanel{
JPanel logGui = null;
JButton registerBut, logBut;
JTextField Login;
public textEmailLog(){
//default characteristics
setSize(700,700);
setName("Email Database");
//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Labels for username and password
JLabel userLab = new JLabel("Username");
JLabel pwLab = new JLabel("Password");
//textfields for username and password
Login = new JTextField("", 15);
JPasswordField Password = new JPasswordField("", 15);
Password.setEchoChar('*');
//login button that confirms username and password
logBut = new JButton("Login");
logBut.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
//needs regex checks prior to logging in
if(e.getSource() == logBut){
/* Change the panel to the homepage
if(Login.getText().equals() && Password.getText().equals()){
}
*/
new homePage();
}
}
});
registerBut = new JButton("Register");
registerBut.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == registerBut){
//Change the panel to the register panel
}
}
});
//Box layout for organization of jcomponents
Box verticalContainer = Box.createVerticalBox();
Box horizontalContainer = Box.createHorizontalBox();
Box mergerContainer = Box.createVerticalBox();
//add to panel
verticalContainer.add(Box.createVerticalStrut(300));//begin relative to the center
verticalContainer.add(userLab);//Login label and text
verticalContainer.add(Login);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(pwLab);//password label and text
verticalContainer.add(Password);
verticalContainer.add(Box.createVerticalStrut(5));
horizontalContainer.add(registerBut);//register button
horizontalContainer.add(Box.createHorizontalStrut(5));
horizontalContainer.add(logBut);//login button
//combines both the vertical and horizontal container
mergerContainer.add(verticalContainer);
mergerContainer.add(horizontalContainer);
add(mergerContainer);
//this.add(logGui);
setVisible(true);
}
}
My Register panel class
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
//No Panel addition
public class Register extends JPanel{
JButton submit, previous;
JLabel firstLab, lastLab, userLab, passwordLab, repassLab, address, emailAdd, errorLabel;
JTextField firstText, lastText, userText, addText, emailAddText;
JPasswordField passwordText, repassText;
public Register(){
setSize(700,700);
//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//register values and their labels and textfields
firstLab = new JLabel("First Name: ");
firstText = new JTextField("", 25);
lastLab = new JLabel("Last Name: ");
lastText = new JTextField("", 40);
userLab = new JLabel("Username: ");
userText = new JTextField("", 25);
passwordLab = new JLabel("Password: ");
passwordText = new JPasswordField("", 25);
passwordText.setEchoChar('*');
repassLab = new JLabel("Confirm Password");
repassText = new JPasswordField("", 25);
repassText.setEchoChar('*');
address = new JLabel("Address: ");
addText = new JTextField("", 50);
emailAdd = new JLabel("Email Address: ");
emailAddText = new JTextField("", 50);
//error message for reigstration issues
errorLabel = new JLabel();
errorLabel.setForeground(Color.red);
submit = new JButton("Submit");
submit.addActionListener(new ActionListener(){
@SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == submit){
//confirm with regex methods and if statements that have been created and need to be created
if(firstText.getText().length() == 0){
errorLabel.setText("*You have not entered a first name!");
}else
if(lastText.getText().length() == 0){
errorLabel.setText("*You have not entered a last name!");
}else
if(userText.getText().length() == 0){
errorLabel.setText("*You have not entered a username!");
}else
if(passwordText.toString().length() == 0){
errorLabel.setText("*You have not entered a Password!");
}else
if(repassText.toString().length() == 0){
errorLabel.setText("*You have not matched your password!");
}
if(addText.getText().length() == 0){
errorLabel.setText("*You have not entered an address!");
}else
if(emailAddText.getText().length() == 0){
errorLabel.setText("*You have not entered an Email address!");
}else
if(userText.getText().length() < 8){
errorLabel.setText("*Username is too short!");
}
else
if(!(passwordText.toString().matches(repassText.toString()))){
errorLabel.setText("Passwords do not match!");
}
else
if(!isValidEmailAddress(emailAddText.getText())){
errorLabel.setText("*Invalid Email!");
}
else
if(!isValidAddress(addText.getText())){
errorLabel.setText("*Invalid Address!");
}
}
}
});
//returns to the previous page
previous = new JButton("Previous Page");
previous.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == previous){
//card.show(login panel);
}
}
});
Box verticalContainer = Box.createVerticalBox();
Box horizontalContainer = Box.createHorizontalBox();
Box mergerContainer = Box.createVerticalBox();
verticalContainer.add(Box.createVerticalStrut(150));
verticalContainer.add(firstLab);
verticalContainer.add(firstText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(lastLab);
verticalContainer.add(lastText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(userLab);
verticalContainer.add(userText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(passwordLab);
verticalContainer.add(passwordText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(repassLab);
verticalContainer.add(repassText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(address);
verticalContainer.add(addText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(emailAdd);
verticalContainer.add(emailAddText);
verticalContainer.add(Box.createVerticalStrut(5));
//horizontal
verticalContainer.add(Box.createVerticalStrut(5));
horizontalContainer.add(submit);
horizontalContainer.add(Box.createHorizontalStrut(5));
horizontalContainer.add(previous);
//merger
mergerContainer.add(verticalContainer);
mergerContainer.add(horizontalContainer);
add(mergerContainer);
setVisible(true);
}
//regex check for valid Email
public boolean isValidEmailAddress(String email){
java.util.regex.Pattern p = java.util.regex.Pattern.compile("[A-Za-z0-9._\\%-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}");
java.util.regex.Matcher m = p.matcher(email);
return m.matches();
}
//regex check for valid Address
public boolean isValidAddress(String address){
java.util.regex.Pattern p = java.util.regex.Pattern.compile("\\d{1,3}.?\\d{0,3}\\s[a-zA-Z]{2,30}\\s[a-zA-Z]{2,15}");
java.util.regex.Matcher m = p.matcher(address);
return m.matches();
}
}
Homepage panel class
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
//NO Panel Yet
@SuppressWarnings("serial")
public class homePage extends JPanel{
JButton uploadEmail, viewEmail;
public homePage(){
setSize(700,700);
uploadEmail = new JButton("Upload Your Email");
uploadEmail.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == uploadEmail){
new loadEmail();
}
}
});
viewEmail = new JButton("View An Email");
viewEmail.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == viewEmail){
new emailView();
}
}
});
add(uploadEmail);
add(viewEmail);
setVisible(true);
}
}
My View Email Panel
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class emailView extends JPanel{
JPanel viewPanel;
JButton logout, delete, homepage;
JTable emailList;
//Cannot be edited or may be in a new panel
/*
JLabel fileLab, toLab, fromLab, subjectLab,topicLab, emailLab, notesLab, attachLab;
JTextField fileText, toText, fromText, subjectText, topicText;
JTextArea emailText, notesText, attachText;
*/
public emailView(){
setSize(700,700);
setVisible(true);
emailList = new JTable();
logout = new JButton("Logout");
logout.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == logout){
new textEmailLog();
}
}
});
delete = new JButton("Delete");
delete.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == delete){
}
}
});
homepage = new JButton("HomePage");
homepage.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == homepage){
new homePage();
}
}
});
Box horizontalContainer = Box.createHorizontalBox();
Box verticalContainer = Box.createVerticalBox();
Box mergerContainer = Box.createVerticalBox();
horizontalContainer.add(logout);
horizontalContainer.add(Box.createHorizontalStrut(5));
horizontalContainer.add(homepage);
horizontalContainer.add(Box.createHorizontalStrut(5));
horizontalContainer.add(delete);
horizontalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(emailList);
mergerContainer.add(horizontalContainer);
mergerContainer.add(verticalContainer);
add(mergerContainer);
setVisible(true);
}
}
My upload Email Panel
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class loadEmail extends JPanel{
JPanel loadPanel;
JLabel fileLab, toLab, fromLab, subjectLab, topicLab, emailLab, notesLab, attachLab;
JTextField fileText, toText, fromText, subjectText, topicText;
JTextArea emailText, notesText, attachText; //attachment text will be changed
JButton cancel, complete, enter;//enter may not be necessary
public loadEmail(){
setSize(700,700);
fileLab = new JLabel("Enter a new File: ");
fileText = new JTextField();
enter = new JButton("Enter");
enter.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == enter){
//opens file directory window
}
}
});
toLab = new JLabel("To: ");
toText = new JTextField();
toText.setSize(5, 30);
fromLab = new JLabel("From: ");
fromText = new JTextField();
subjectLab = new JLabel("Subject: ");
subjectText = new JTextField();
topicLab = new JLabel("Topic: ");
topicText = new JTextField();
emailLab = new JLabel("Email Content: ");
emailText = new JTextArea();
notesLab = new JLabel("Comments: ");
notesText = new JTextArea();
attachLab = new JLabel("Attachments");
attachText = new JTextArea();
cancel = new JButton("Cancel");
cancel.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == cancel){
//dispose page
}
}
});
complete = new JButton("Complete");
complete.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == complete){
//store in database, prompt user for new email to enter in other wise return to homepage
}
}
});
Box verticalContainer = Box.createVerticalBox();
Box horizontalContainer = Box.createHorizontalBox();
Box mergerContainer = Box.createVerticalBox();
verticalContainer.add(fileLab);
verticalContainer.add(fileText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(Box.createHorizontalStrut(50));
verticalContainer.add(enter);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(toLab);
verticalContainer.add(toText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(fromLab);
verticalContainer.add(fromText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(subjectLab);
verticalContainer.add(subjectText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(topicLab);
verticalContainer.add(topicText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(emailLab);
verticalContainer.add(emailText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(notesLab);
verticalContainer.add(notesText);
verticalContainer.add(Box.createVerticalStrut(5));
verticalContainer.add(attachLab);
verticalContainer.add(attachText);
verticalContainer.add(Box.createVerticalStrut(5));
horizontalContainer.add(cancel);
horizontalContainer.add(Box.createHorizontalStrut(5));
horizontalContainer.add(complete);
mergerContainer.add(verticalContainer);
mergerContainer.add(horizontalContainer);
add(mergerContainer);
setVisible(true);
}
}
The short answer is don't. The reasons for this is you'll end having to expose the parent container and CardLayout
to ALL your sub components, which not only exposes portions of your application to potential mistreatment, it tightly couples the navigation making it difficult to add/remove steps in the future...
A better solution would be to devise some kind of controller interface
, which defines what each view could do (for example showHome
, nextView
, previousView
), you would then pass an implementation of this interface to each view. Each view would then use this interface to request a change as the needed to.
The controller would know things like, the current view, the home view and how to move between certain views (next/previous) as required.
Updated with simple example
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ContainerAdapter;
import java.awt.event.ContainerEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AllYouViewBelongToMe {
public static void main(String[] args) {
new AllYouViewBelongToMe();
}
public AllYouViewBelongToMe() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface ViewContoller {
public void goHome();
public void nextView();
public void previousView();
}
public static class DefaultViewController implements ViewContoller {
public static final String HOME = "home";
private Component currentView = null;
private List<Component> views;
private Map<Component, String> mapNames;
private Container parent;
private CardLayout cardLayout;
public DefaultViewController(Container parent, CardLayout cardLayout) {
this.parent = parent;
this.cardLayout = cardLayout;
views = new ArrayList<>(25);
mapNames = new HashMap<>(25);
}
public CardLayout getCardLayout() {
return cardLayout;
}
public Container getParent() {
return parent;
}
public void addView(Component comp, String name) {
if (!HOME.equals(name)) {
views.add(comp);
}
mapNames.put(comp, name);
getParent().add(comp, name);
}
public void removeView(Component comp, String name) {
views.remove(comp);
mapNames.remove(comp);
getParent().remove(comp);
}
@Override
public void goHome() {
currentView = null;
getCardLayout().show(getParent(), HOME);
}
@Override
public void nextView() {
if (views.size() > 0) {
String name = null;
if (currentView == null) {
currentView = views.get(0);
name = mapNames.get(currentView);
} else {
int index = views.indexOf(currentView);
index++;
if (index >= views.size()) {
index = 0;
}
currentView = views.get(index);
name = mapNames.get(currentView);
}
getCardLayout().show(getParent(), name);
}
}
@Override
public void previousView() {
if (views.size() > 0) {
String name = null;
if (currentView == null) {
currentView = views.get(views.size() - 1);
name = mapNames.get(currentView);
} else {
int index = views.indexOf(currentView);
index--;
if (index < 0) {
index = views.size() - 1;
}
currentView = views.get(index);
name = mapNames.get(currentView);
}
getCardLayout().show(getParent(), name);
}
}
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
CardLayout cardLayout = new CardLayout();
JPanel view = new JPanel(cardLayout);
final DefaultViewController controller = new DefaultViewController(view, cardLayout);
controller.addView(createPane("home"), DefaultViewController.HOME);
controller.addView(createPane("Page #1"), "View1");
controller.addView(createPane("Page #2"), "View2");
controller.addView(createPane("Page #3"), "View3");
controller.addView(createPane("Page #4"), "View4");
controller.goHome();
JPanel controls = new JPanel();
JButton btnPrev = new JButton("<");
JButton btnHome = new JButton("Home");
JButton btnNext = new JButton(">");
controls.add(btnPrev);
controls.add(btnHome);
controls.add(btnNext);
btnNext.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.nextView();
}
});
btnPrev.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.previousView();
}
});
btnHome.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.goHome();
}
});
add(view);
add(controls, BorderLayout.SOUTH);
}
protected JPanel createPane(String name) {
JPanel panel = new JPanel(new GridBagLayout());
panel.add(new JLabel(name));
return panel;
}
}
}