简体   繁体   English

在相同/链接的JPanel actionlistener之前,JFrame actionlistener正在激活

[英]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. 我有一个JFrame作为默认菜单,并且有一个JPanel出现在其中以处理登录。 After a successful login the JPanel is supposed to send the login information to JFrame so it knows who is currently logged in. 成功登录后,JPanel应该将登录信息发送到JFrame,以便它知道当前登录的人。

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. 问题在于,单击JButton时,在JPanel有机会检查凭据之前,它正在激活发送部分(其代码为JFrame)。 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. 成功登录后,DetailsPanel应该将信息发送到GUIFrame,然后GUIFrame登录。

Instead, when actionlistener occurs, the GUIFrame attemps to login before DetailsPanel gets to check the credentials and send it to GUIFrame. 而是在发生动作侦听器时,GUIFrame尝试在DetailsPanel检查凭据并将其发送到GUIFrame之前登录。

Is there a way to get the DetailsPanel.addActionListener() to come AFTER the logIn.addActionListener()? 有没有办法在LogIn.addActionListener()之后获取DetailsPanel.addActionListener()?

The order of events is generally not guaranteed. 通常不保证事件的顺序。 Observationally, they tend to be trigged in FILO (first in, last out) order. 观察到,它们倾向于按FILO(先进先出)顺序触发。

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 一种“简单”的解决方案是使用现有的API功能

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 . 因此,基本上(或确实如此)是将“已注册” ActionListener存储在可用的listenerList This is API provided by Swing available to all Swing components. 这是Swing提供的API,可用于所有Swing组件。

When the button is clicked and the identity verified, all registered parties are notified, via the fireActionPerformed method. 单击该按钮并验证身份后,将通过fireActionPerformed方法通知所有注册方。

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 一个更完整的解决方案可能涉及您自己的事件侦听器interface ,其中可能包括validationSuccessvalidationUnsuccessful并且可以将用户凭据作为事件对象的一部分传回

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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