我正在开发一个登录验证器,有一个类可以检查用户名和密码的有效性。检查后,在LoginPxy类中更新一个布尔变量(isValidLoginCredentials(,该变量可以通过get方法获取并用于其他目的。但是,get方法返回的值始终是创建类时我分配给isValidLoginCredentials的默认值。我认为问题是,在有机会更新isValidLoginCredentials之前,我正在main((中调用getter方法,但我不知道应该做什么更改来阻止这种情况。这是课程和主程序的相关部分。
public class LoginProxy implements ActionListener
{
private JLabel usernameLabel;
private JTextField usernameText;
private JLabel passwordLabel;
private JPasswordField passwordText;
private JButton loginButton;
private boolean isValidLoginCredentials = false;
public void createLogin()
{
/*Here was code irrelevant to the problem I removed*/
loginButton.addActionListener(new LoginProxy());
loginButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String user = usernameText.getText();//get the username
String pass = passwordText.getText();//get the password
String credentials = user +":"+pass;//creates the string I compare to other valid
//credentials
ConcreteLoginValidator validator = new ConcreteLoginValidator(credentials);
try
{
isValidLoginCredentials = validator.checkLogin();
System.out.println("The credentials are "+isValidLoginCredentials);
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
}
});
}
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
}
public boolean getValidity()
{
return isValidLoginCredentials;
}
这是的主要方法
public static void main(String[] args)
{
boolean isValidLogin = false;
LoginProxy proxy = new LoginProxy();
proxy.createLogin();
isValidLogin = proxy.getValidity();
if(isValidLogin == true)
{
JFrame frame = MainUI.getInstance();
frame.setSize(900, 600);
frame.pack();
frame.setVisible(true);
}
}
我应该添加什么以使isValidLogin=proxy.getValidaty((;只有在我已经输入并检查登录凭据是否正确后才返回值?
直截了当地说,一个快速的解决方案是将代码放在下面:
if(isValidLoginCredentials) {
JFrame frame = MainUI.getInstance();
frame.setSize(900, 600);
frame.pack();
frame.setVisible(true);
}
此部分之后:
System.out.println("The credentials are "+isValidLoginCredentials);
您在createLogin((上调用的代码只是将动作侦听器设置为UI中的按钮,因此代码将在您单击按钮时执行。最重要的是,当你打开一个窗口时,它会启动一个单独的线程。我不知道其余的代码,但假设当您实例化LoginPxy时,它会打开登录窗口。但按照您的书写方式,它会打开窗口并立即检查isValidLogin(它不会等待您单击按钮(。
如果你想证明这一点,你可以简单地在proxy.createLogin((之前和之后放一个System.out.println。你会意识到,在呈现UI时,这两行都会被访问。
使用一个模式对话框,该对话框会一直阻塞到关闭。
非常简单的例子:
public class Dialog { // LoginProxy in questions code
private String value = null;
public void show(Window owner) {
var dialog = new JDialog(owner, JDialog.DEFAULT_MODALITY_TYPE);
var field = new JTextField(40);
var okButton = new JButton("OK");
okButton.addActionListener(ev -> {
value = field.getText();
dialog.dispose();
});
var panel = new JPanel();
panel.add(field);
panel.add(okButton);
dialog.add(panel);
dialog.pack();
dialog.setLocationRelativeTo(owner);
dialog.setVisible(true); // this will be blocked until JDialog is closed
}
public String getValue() {
return value;
}
}
称为类似
public static void main(String[] args) {
var dialog = new Dialog();
dialog.show(null);
System.out.println(dialog.getValue()); // check if valid and open JFrame in questions code
}
此解决方案的优点IMHO:对话框类(LoginProxy
(不需要知道关于主类和主JFrame
。它有一个明确的单一功能:请求用户输入。
使用JOptionPane
创建对话框更加容易
为了保证读取在另一个线程中写入的值,必须使字段volatile
:
private volatile boolean isValidLoginCredentials;
你也必须等到另一个完成后再阅读。这方面我留给读者。