Use a CardLayout
See for How to Use CardLayout more details.
This will encourage you to isolate you functionality into individual components, there by isolating the workflows and supporting the "single responsibility" concept.
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
private UserPane userPane;
private LoginPane loginPane;
public MainPane() {
setLayout(new CardLayout());
userPane = new UserPane();
loginPane = new LoginPane(new AuthenticationListener() {
@Override
public void authenticationWasSuccessful(User user) {
userPane.setUser(user);
// The user pane's content size will have changed
SwingUtilities.windowForComponent(userPane).pack();
((CardLayout) getLayout()).show(MainPane.this, "USER");
}
@Override
public void authenticationDidFail() {
JOptionPane.showMessageDialog(MainPane.this, "Authentication failed", "Error", JOptionPane.ERROR_MESSAGE);
}
});
add(userPane, "USER");
add(loginPane, "LOGIN");
((CardLayout) getLayout()).show(this, "LOGIN");
}
}
public interface User {
public String getName();
}
public class DefaultUser implements User {
private String name;
public DefaultUser(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
public interface AuthenticationListener {
public void authenticationWasSuccessful(User user);
public void authenticationDidFail();
}
public class LoginPane extends JPanel {
private JTextField user;
private JPasswordField password;
private JButton login;
private AuthenticationListener loginListener;
public LoginPane(AuthenticationListener listener) {
setBorder(new EmptyBorder(32, 32, 32, 32));
this.loginListener = listener;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("User name:"), gbc);
gbc.gridy++;
add(new JLabel("Password:"), gbc);
gbc.gridx++;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
user = new JTextField(12);
password = new JPasswordField(12);
add(user, gbc);
gbc.gridy++;
add(password, gbc);
login = new JButton("Login");
gbc.gridx = 0;
gbc.gridy++;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(login, gbc);
login.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean accept = (boolean) (((int) Math.round(Math.random() * 1)) == 0 ? true : false);
if (accept) {
loginListener.authenticationWasSuccessful(new DefaultUser(user.getText()));
} else {
loginListener.authenticationDidFail();
}
}
});
}
}
public class UserPane extends JPanel {
private JLabel userLabel;
public UserPane() {
JLabel label = new JLabel("Welcome!");
Font font = label.getFont();
label.setFont(font.deriveFont(Font.BOLD, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
add(label, gbc);
userLabel = new JLabel();
add(userLabel, gbc);
}
public void setUser(User user) {
userLabel.setText(user.getName());
}
}
}
Use a modal JDialog
See How to Make Dialogs for more details.
More windows isn't always a good choice, but in the context of gathering user credentials, I think you can make an argument.
This makes use of a modal dialog to stop the code execution at the point that the window is made visible and it won't continue until the window is closed. This allows you an opportunity to get and validate the user credentials before the code continues (it's black magic in how it works, but it's a very common workflow)
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
User user = LoginPane.showLoginDialog();
if (user != null) {
JFrame frame = new JFrame();
frame.add(new UserPane(user));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} else {
// Well, you really don't know do you? Did they cancel
// the dialog or did authentication fail?
}
}
});
}
public interface User {
public String getName();
}
public static class DefaultUser implements User {
private String name;
public DefaultUser(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
public static class LoginPane extends JPanel {
public interface AuthenticationListener {
public void authenticationWasSuccessful(User user);
public void authenticationDidFail();
}
private JTextField userTextField;
private JPasswordField passwordField;
private JButton loginButton;
private User user;
public LoginPane(AuthenticationListener listener) {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("User name:"), gbc);
gbc.gridy++;
add(new JLabel("Password:"), gbc);
gbc.gridx++;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
userTextField = new JTextField(12);
passwordField = new JPasswordField(12);
add(userTextField, gbc);
gbc.gridy++;
add(passwordField, gbc);
loginButton = new JButton("Login");
gbc.gridx = 0;
gbc.gridy++;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(loginButton, gbc);
loginButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean accept = (boolean) (((int) Math.round(Math.random() * 1)) == 0 ? true : false);
if (accept) {
user = new DefaultUser(userTextField.getText());
listener.authenticationWasSuccessful(user);
} else {
user = null;
listener.authenticationDidFail();
}
}
});
}
public User getUser() {
return user;
}
public static User showLoginDialog() {
JDialog dialog = new JDialog();
dialog.setTitle("Login");
dialog.setModal(true);
LoginPane loginPane = new LoginPane(new LoginPane.AuthenticationListener() {
@Override
public void authenticationWasSuccessful(User user) {
dialog.dispose();
}
@Override
public void authenticationDidFail() {
JOptionPane.showMessageDialog(dialog, "Authentication failed", "Error", JOptionPane.ERROR_MESSAGE);
}
});
dialog.add(loginPane);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
return loginPane.getUser();
}
}
public class UserPane extends JPanel {
public UserPane(User user) {
setBorder(new EmptyBorder(32, 32, 32, 32));
JLabel label = new JLabel("Welcome!");
Font font = label.getFont();
label.setFont(font.deriveFont(Font.BOLD, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
add(label, gbc);
JLabel userLabel = new JLabel();
userLabel.setText(user.getName());
add(userLabel, gbc);
}
}
}