我有一个GUI,添加了登录提示。
while(notValidLogIn){ LoginPrompt.getDetails() //a static method that }
但是,loginPrompt是带有父JFrame的Jdialog。如何停止单击的取消循环,我可以将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 处理这些LoginEvents的接口:
public interface LoginListener extends EventListener { public void handleLoginEvent(LoginEvent evt); }
登录对话框 此类必须List订阅一个LoginListeners:
class LoginDialog { List<LoginListener> 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); } } }
将动作侦听器添加到accept和cancel按钮:
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();
如果此循环位于EDT(事件分发线程)以外的另一个线程内,则可以使用SwingUtilities.invokeAndWait(new Runnable())function:invokeAndWait()阻塞当前线程,直到EDT执行完它所给的任务为止。当我们要等待线程执行以从用户或其他使用JDialogue/JFileChooseretc进行确认的线程执行时,此选项特别有用
SwingUtilities.invokeAndWait(new Runnable())function:invokeAndWait()
JDialogue/JFileChooseretc
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();