Java swing - при нажатии кнопки отмены не зацикливаться

У меня есть графический интерфейс, к которому добавлено приглашение на вход.

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()
}

2 ответа

Решение

В недавнем проекте, над которым я работал, я реализовал решение на основе событий. Идея 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();
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() ;
       }
    });

  }

Примечание: еще раз подчеркнув: вы должны убедиться, что этот цикл выполняется внутри другого потока: например, с использованием расширенного класса 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();
Другие вопросы по тегам