我已经在网上四处寻找如何从现有JFrame中打开新的JFrame。我发现显然最好的方法是处置现有的JFrame并打开新的JFrame-但这是一个问题。
我有一个登录表单,一个用户登录,放置了登录框架,并且将主框架设置为可见。
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class client {
public static void main(String[] args) {
initialize();
}
private static void initialize() {
JFrame loginFrame = new JFrame("Login");
loginFrame.setBounds(100, 100, 300, 300);
loginFrame.setResizable(false);
loginFrame.setLocationRelativeTo(null);
loginFrame.setDefaultCloseOperation(loginFrame.HIDE_ON_CLOSE);
loginFrame.getContentPane().setLayout(null);
JFrame mainFrame = new JFrame("Main");
mainFrame.setBounds(100, 100, 300, 197);
mainFrame.setResizable(false);
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(mainFrame.EXIT_ON_CLOSE);
mainFrame.getContentPane().setLayout(null);
JButton loginButton = new JButton("Login");
loginButton.setBounds(102, 133, 89, 23);
loginButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
loginButton.setEnabled(false);
loginFrame.dispose();
mainFrame.setVisible(true);
}
});
loginFrame.getContentPane().add(loginButton);
loginFrame.setVisible(true);
}
}
但是,如果用户启动客户端,然后决定不登录并关闭它,该进程仍在后台运行?
我觉得这是一个非常愚蠢的问题,如果真是这样,我很抱歉,但是我环顾四周,找不到任何解决方法。我可以不丢弃登录框架而将其隐藏并将它们都设置为EXIT_ON_CLOSE吗?
谢谢!
答案 0 :(得分:2)
因此,主要问题是,您有两个框架,虽然不可见,但都已“实现”,这意味着在所有应用程序窗口都被处理掉之前,事件调度线程不会退出,这意味着JVM不会退出。
因此,我建议在方法上稍作更改。而不是以这种方式使用两个框架,登录“窗口”应该基于模式对话框,并且除非需要,否则不应该创建应用程序框架。
模态拨号将在可见的那一刻停止执行代码,这不会阻塞事件调度线程(这是不可思议的事情),这意味着您可以使用它作为循环来不断提示用户输入凭据,直到它们通过身份验证或关闭/取消对话框。
我也强烈建议使用JPanel
作为基础组件,允许将基于窗口的类仅作为容器,这可以隔离责任,分离代码并提供整体上更可重用的解决方案。
您可以查看How to Make Dialogs了解更多详细信息
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
LoginPane loginPane = new LoginPane();
boolean authenticated = false;
boolean exit = false;
do {
int option = JOptionPane.showOptionDialog(null,
loginPane,
"login",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
new Object[]{"Login", "Cancel"},
"Login");
if (option == 0) {
// Authenticate
authenticated = true;
} else if (option == JOptionPane.CLOSED_OPTION || option == 1) {
exit = true;
}
} while (!authenticated && !exit);
if (authenticated) {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
});
}
public class LoginPane extends JPanel {
private JTextField userName;
private JPasswordField password;
public LoginPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(new JLabel("User name: "), gbc);
gbc.gridy++;
add(new JLabel("Password: "), gbc);
gbc.gridx++;
gbc.gridy = 0;
userName = new JTextField(10);
password = new JPasswordField(10);
add(userName, gbc);
gbc.gridy++;
add(password, gbc);
}
public String getName() {
return userName.getText();
}
public char[] getPassword() {
return password.getPassword();
}
}
public class MainPane extends JPanel {
public MainPane() {
setBorder(new EmptyBorder(50, 50, 50, 50));
add(new JLabel("Super awesome app"));
}
}
}
我也鼓励使用DISPOSE_ON_CLOSE
而不是HIDE_ON_CLOSE
,它将释放本机同级并从应用程序窗口缓存中删除该窗口
现在,如果您真的想使用更具挑战性的方法,可以看看Java and GUI - Where do ActionListeners belong according to MVC pattern?,它介绍了基于MVC的登录实现