NimChimpsky
NimChimpsky

Reputation: 47280

Java swing - when cancel button clicked don't loop

I have a gui, that is having a Login prompt added.

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

Hwoever, the loginPrompt is a Jdialog, with a parent JFrame. How can I stop looping of cancel clicked, I could put System.exit(0) in cancel action performed. But don't want to stop everything, I want something like :

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

Upvotes: 0

Views: 1236

Answers (2)

dic19
dic19

Reputation: 17971

In a recent project I was working on, I've implemented an event based solution. The idea is JDialog notify to its parent JFrame how the login process went and this last one may or may not continue its execution. This way I have no loops and keep separate responsibilities: The schema would be something like this:

LoginEvent:

This is the event itself. Not that complicated:

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

An interface to handle these LoginEvents:

public interface LoginListener extends EventListener {

    public void handleLoginEvent(LoginEvent evt);

}

Login Dialog

This class has to mantain a List with subscribed 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);
        }
    }
}

Adding action listeners to accept and cancel buttons:

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

Subscribing a LoginListener

In your 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();

Upvotes: 1

Sage
Sage

Reputation: 15408

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

If this loop is inside another thread other than the EDT(event dispatch thread), then you can use SwingUtilities.invokeAndWait(new Runnable()) function: invokeAndWait() blocks the current thread until the EDT is done executing the task given by it. This option is particularly used while we want to await an execution of a thread for taking confirmation from user or other input using JDialogue/JFileChooser etc

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

  }

Note: re-stating for emphasizing: you should ensure that this loop is executing inside another Thread: such as using an extended class of Runnable, or by means of anonymous class:

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

Upvotes: 1

Related Questions