Reputation: 91
So I want to have a CardLayout class that switches between a menu page and a main app page, but I want to design those two panels in their own classes, then add an ActionListener and a CardLayout in a different class, and have the ActionListener use a button created in one of the panel classes.
Here is a (Not so short) SSCCE that kind of covers what I'm trying to say:
import java.awt.*;
import javax.swing.*;
public class MenuPanel extends Frame{
JPanel menuPanel;
JButton login;
JButton signup;
public MenuPanel(){
menuPanel = new JPanel(new GridBagLayout());
login = new JButton("Login");
signup = new JButton("Signup");
menuPanel.add(login);
menuPanel.add(signup);
}
}
import java.awt.*;
import javax.swing.*;
public class MainPanel extends JFrame{
JPanel menuPanel;
JButton login;
JButton signup;
public MainPanel(){
mainPanel = new JPanel(new GridBagLayout());=
menuPanel.setBackground(Color.grey);
}
}
import java.awt.*;
import javax.swing.*;
public class CardLayout extends Frame implements ActionL {
//Now how do I add the frames from the other classes so that I can add them to my CardLayout?
CardLayout cl = new CardLayout();
JPanel panelCont;
public CardLayout() {
frame.add(panelCont);
panelCont = new JPanel(cl);
//Here is where I'm having trouble
panelCont.add(menuPanel, "1");
panelCont.add(mainPanel, "2");
cl.show(panelCont, "1");
login.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
cl.show(panelCont, "2");
}
});
}
}
public class Main {
public static void main(String[] args) {
new CardLayout();
}
}
Upvotes: 2
Views: 99
Reputation: 51515
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Concurrency in Swing and the Laying Out Components Within a Container sections.
In Java Swing, you create one JFrame
and as many JPanels
as you need to create the GUI.
I created a card JPanel
, a menu JPanel
, and a login JPanel
in three separate classes. The card JPanel
class creates the JPanel
with the CardLayout
. The menu JPanel
creates the JPanel
that contains the menu JButtons
. The login JPanel class creates the JPanel
that contains the login Swing components.
Here's the JFrame
with the menu JPanel
.
Here's the GUI after you left-click on the Login JButton
.
Notice how I named the classes. CardPanel
, MenuPanel
, LoginPanel
. By appending Panel to the end of the class name, that tells me they use a JPanel
.
When I create a separate ActionListener
class, I'd name it ButtonListener
or SignupListener
.
The only ActionListener
I created ties the menu login JButton
to displaying the login JPanel
. Since it consists of one line, I made it an anonymous class using a lambda expression.
Here's the complete runnable code. I made all the additional classes inner classes so I could post this code as one block. You can and should put these classes in separate files.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class CardLayoutExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new CardLayoutExample());
}
@Override
public void run() {
JFrame frame = new JFrame("CardLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CardPanel().getPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class CardPanel {
private final CardLayout cardLayout;
private final JPanel panel;
public CardPanel() {
this.cardLayout = new CardLayout();
this.panel = createCardPanel();
}
private JPanel createCardPanel() {
JPanel panel = new JPanel(cardLayout);
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.add(new MenuPanel(this).getPanel(), "menu");
panel.add(new LoginPanel().getPanel(), "login");
return panel;
}
public void showLoginPanel() {
cardLayout.show(panel, "login");
}
public JPanel getPanel() {
return panel;
}
}
public class MenuPanel {
private final CardPanel cardPanel;
private final JPanel panel;
public MenuPanel(CardPanel cardPanel) {
this.cardPanel = cardPanel;
this.panel = createMenuPanel();
}
private JPanel createMenuPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton login = new JButton("Login");
login.addActionListener(event -> cardPanel.showLoginPanel());
panel.add(login);
JButton signup = new JButton("Signup");
panel.add(signup);
return panel;
}
public JPanel getPanel() {
return panel;
}
}
public class LoginPanel {
private final JPanel panel;
private final JPasswordField passwordField;
private final JTextField useridField;
public LoginPanel() {
this.useridField = new JTextField(30);
this.passwordField = new JPasswordField(30);
this.panel = createLoginPanel();
}
private JPanel createLoginPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
JLabel label = new JLabel("Userid:");
panel.add(label, gbc);
gbc.gridx++;
panel.add(useridField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Password:");
panel.add(label, gbc);
gbc.gridx++;
panel.add(passwordField, gbc);
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = 2;
gbc.gridx = 0;
gbc.gridy++;
JButton button = new JButton("Submit");
panel.add(button, gbc);
return panel;
}
public String getUserid() {
return useridField.getText();
}
public char[] getPassword() {
return passwordField.getPassword();
}
public JPanel getPanel() {
return panel;
}
}
}
Upvotes: 2
Reputation: 35061
You cannot add Frame
s to another component. Frame
is a top level component with a native peer. You should subclass from something else (JPanel?) instead
Also, btw what you are doing is not good design. Generally, in MVC Swing design, all view and control aspects should be in one class. Don't split the view into multiple classes unless each of those classes stands up as its own reusable widget
Upvotes: 3