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); } } }
添加动作侦听器以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();
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();