Java swing – 当点击取消按钮时不循环

我有一个gui,即添加了一个登录提示。

while(notValidLogIn){ LoginPrompt.getDetails() //a static method that } 

但是,loginPrompt是一个Jdialog,具有父JFrame。 如何停止点击取消的循环,我可以将System.exit(0)置于取消操作中。 但是不要想要阻止一切,我想要的是:

 while(notValidLogIn && LoginPrompt.isNotCancelled()){ LoginPrompt.getDetails(); //a static method that creates an instance of login JDialog() } 

在我最近的一个项目中,我已经实现了一个基于事件的解决方案。 想法是JDialog通知其父JFrame登录过程如何进行,最后一个可能会或可能不会继续执行。 这样我就没有循环并且保持不同的职责:模式将是这样的:

为LoginEvent:

这是事件本身。 没那么复杂:

 class LoginEvent extends EventObject { public static final int LOGIN_SUCCEEDED = 0; public static final int LOGIN_FAILED = 1; public static final int LOGIN_DIALOG_CLOSED = 2; private int id; public LoginEvent(Object source, int id) { super(source); this.id = id; } public int getId() { return id; } } 

LoginListener

处理这些LoginEvent的接口:

 public interface LoginListener extends EventListener { public void handleLoginEvent(LoginEvent evt); } 

登录对话框

这个类必须使用订阅的LoginListeners List

 class LoginDialog { List listeners = new ArrayList<>(); JDialog dialog; JButton accept; JButton cancel; public void show() { //create and show GUI components } public void close() { if(dialog != null) { dialog.dispose(); } } ... public void addLoginListener(LoginListener loginEventListener) { if(!listeners.contains(loginEventListener)) { listeners.add(loginEventListener); } } public void removeLoginListener(LoginListener loginEventListener) { listeners.remove(loginEventListener); } public void dispatchLoginEvent(LoginEvent evt) { for(LoginListener loginListener: listeners) { loginListener.handleLoginEvent(evt); } } } 

添加动作侦听器以acceptcancel按钮:

  accept.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // validate login data if(loginValid) { dispatchLoginEvent(new LoginEvent(dialog, LoginEvent.LOGIN_SUCCEEDED)); } else { dispatchLoginEvent(new LoginEvent(dialog, LoginEvent.LOGIN_FAILED)); } } }); cancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dispatchLoginEvent(new LoginEvent(dialog, LoginEvent.LOGIN_DIALOG_CLOSED)); } }); 

订阅LoginListener

在你的JFrame

  final LoginDialog dialog = new LoginDialog(); dialog.addLoginListener(new LoginListener() { @Override public void handleLoginEvent(LoginEvent evt) { if(evt.getId() == LoginEvent.LOGIN_SUCCEEDED { dialog.close(); //continue execution return; } if(evt.getId() == LoginEvent.LOGIN_FAILED) { JOptionPane.showMessageDialog(null, "Login failed!"); return; } if(evt.getId() == LoginEvent.CLOSE_LOGIN_DIALOG) { dialog.close(); // do something when this dialog is closed } } }; dialog.show(); 
 while(notValidLogIn && LoginPrompt.isNotCancelled()){ LoginPrompt.getDetails(); //a static method that creates an instance of login JDialog() } 

如果此循环位于除EDT(事件调度线程)之外的另一个线程内,则可以使用SwingUtilities.invokeAndWait(new Runnable())函数: invokeAndWait()阻止当前线程,直到EDT完成执行由其给出的任务为止。 当我们想要等待执行线程以使用JDialogue/JFileChooser等从用户或其他输入获取确认时,特别使用此选项

 while(notValidLogIn && LoginPrompt.isNotCancelled()){ SwingUtilities.invokeAndWait(new Runnable() { public void run() { LoginPrompt.getDetails() ; } }); } 

注意: 重新说明强调 :你应该确保这个循环在另一个Thread内执行:比如使用Runnable的扩展类,或者通过匿名类:

 new Thread() { // other code of your context public void run() { while(notValidLogIn && LoginPrompt.isNotCancelled()){ SwingUtilities.invokeAndWait(new Runnable() { public void run() { LoginPrompt.getDetails() ; } }); } } }.start();