简体   繁体   中英

JFrame actionlistener is activating before an identical/linked JPanel actionlistener

I'm new to programming and am trying my hand at swing. I have a JFrame that serves as as the default menu, and I have a JPanel that appears in it to handle logins. After a successful login the JPanel is supposed to send the login information to JFrame so it knows who is currently logged in.

The problem is that the JButton, when clicked, is activating the send portion(whose code is the JFrame) before the JPanel has the chance to check the credentials. They are both using the same actionlistener so I don't know how to control the order.

public class GUIFrame extends JFrame {
    private DetailsPanel detailsPanel;
    private String curUsername;
    public GUIFrame(String title){
        super(title);
        detailsPanel = new DetailsPanel();
        setLayout(new BorderLayout());

        Container c = getContentPane();
        c.add(detailsPanel, BorderLayout.EAST);


        detailsPanel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (!(detailsPanel.getCurUsername() == "")){
                    randomToBeImplementedFunctionThatWillLogIn();
                //TODO: 
                // The check here happens BEFORE the detailsPanel processes everything
                // so the first time they create an account it won't log them in
                // and every subsequent time the PREVIOUS login creds will be used. 
            }
        }
    });





public class DetailsPanel extends JPanel {

    private HashMap<String, String> logInMap = new HashMap<String, String>();

    private String curUsername = "";//the current logged in username
    public String getCurUsername(){
        return curUsername;
    }
    JTextField nameField;
    JTextField passField;
    public DetailsPanel(){
        nameField = new JTextField(0);
        passField = new JTextField(0);


    logIn.addActionListener( (e) -> {//login attempted
            if (logInMap.containsKey(nameField.getText())){
                if (passField.getText().equals(logInMap.get(nameField.getText()))){
                    //logged in
                    curUsername = nameField.getText();
                }
                else{
                    //wrong password, logged out
                    curUsername = "";

                }
            }
            else {
                logInMap.put(nameField.getText(), passField.getText());
                curUsername = nameField.getText();
                //create new account
            }


        } );

        GridBagConstraints gCons = new GridBagConstraints();
        gCons.gridy = 0;
        gCons.gridx = 0;
        add(nameField, gCons);
        gCons.gridy = 1;
        add(passField, gCons);
    }
    public void addActionListener(ActionListener al)
    {
        logIn.addActionListener(al);
    }
}

on a successful login, DetailsPanel is supposed to send information to GUIFrame, and then GUIFrame logs in.

Instead, when actionlistener occurs, the GUIFrame attemps to login before DetailsPanel gets to check the credentials and send it to GUIFrame.

Is there a way to get the DetailsPanel.addActionListener() to come AFTER the logIn.addActionListener()?

The order of events is generally not guaranteed. Observationally, they tend to be trigged in FILO (first in, last out) order.

A better solution would be to decouple the process, so any interested parties are not reliant on the button action, but instead on the component telling them when the validation has occurred.

A "simple" solution is to use the existing API functionality

public class DetailsPanel extends JPanel {

    private HashMap<String, String> logInMap = new HashMap<String, String>();

    private String curUsername = "";//the current logged in username

    public String getCurUsername() {
        return curUsername;
    }
    JTextField nameField;
    JTextField passField;

    JButton logIn;

    public DetailsPanel() {
        nameField = new JTextField(0);
        passField = new JTextField(0);

        logIn.addActionListener((e) -> {//login attempted
            if (logInMap.containsKey(nameField.getText())) {
                if (passField.getText().equals(logInMap.get(nameField.getText()))) {
                    //logged in
                    curUsername = nameField.getText();
                    fireActionPerformed();
                } else {
                    //wrong password, logged out
                    curUsername = "";

                }
            } else {
                logInMap.put(nameField.getText(), passField.getText());
                curUsername = nameField.getText();
                //create new account
            }

        });

        GridBagConstraints gCons = new GridBagConstraints();
        gCons.gridy = 0;
        gCons.gridx = 0;
        add(nameField, gCons);
        gCons.gridy = 1;
        add(passField, gCons);
    }

    public void addActionListener(ActionListener al) {
        listenerList.add(ActionListener.class, al);
    }

    protected void fireActionPerformed() {
        ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
        if (listeners.length == 0) {
            return;
        }
        ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "validated");
        for (ActionListener listener : listeners) {
            listener.actionPerformed(evt);
        }
    }

}

So, basically, or this does, is stores the "registered" ActionListener s in the available listenerList . This is API provided by Swing available to all Swing components.

When the button is clicked and the identity verified, all registered parties are notified, via the fireActionPerformed method.

A more complete solution would probably involve your own event listener interface which could include validationSuccess and validationUnsuccessful and could pass back the user credentials as part of the event object

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM