如何在没有显式调用的情况下调用“actionPerformed”方法?

2022-09-04 20:07:20

我刚刚开始用Swing学习GUI,并不完全了解该方法的工作原理。请考虑以下代码:actionPerformed

//code to create a button and change its text when clicked
public class simplegui implements ActionListener {
  JButton button;

  public static void main(String[] args) {
    simplegui gui=new simplegui();
    gui.go();
  }

  public void go() {
    JFrame frame=new Frame();
    button=new JButton("click Me");
    button.addActionListener(this);

    frame.getContentPane().add(button);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300,300);
    frame.setVisible(true);
  }

  public void actionPerformed(ActionEvent event) {
    button.setText("I've been clicked!");
  }
}

难道不应该在调用类上的方法之前为类创建对象(静态方法除外)吗?

单击按钮时,将调用该方法,但如何调用?在哪里拨打电话?我已经实现了接口,但是知道当操作发生时,应将“ActionEvent”对象发送到“actionPerformed”方法的代码在哪里?它是否存在于 Button 类中?该方法是否存在于 Button 类中?actionPerformedActionListeneraddActionListener

当我单击该按钮时,系统调用操作是如何执行的,执行的代码在哪里?gui.actionPerformed()

直到现在,我一直遵循JAVA的OO,静态等概念,但这整个事件驱动的编程令人困惑。


答案 1

每个事件都由一个对象表示,该对象提供有关事件的信息并标识事件源。事件源通常是组件或模型,但其他类型的对象也可以是事件源。

在这里,您注册的听众,即

button.addActionListener(this);

被添加到侦听器列表中,当 JVM 收到事件(在本例中单击)时,它会在列表中的所有侦听器上调用相应的方法。

这是如何发生的?好吧,我认为你应该阅读Java中的机制。Callback

您还可以使用回调机制创建自己的侦听器。请考虑以下代码:

该代码用于信用卡应用模拟。在下面的代码中,当调用该方法时将自动调用该方法。pinChanged()changePin()

public interface PinChangeListener {
    public void pinChanged();
}

public class CreditCard {
    public PinChangeListener pinChangeListener;

    private int pin;

    public changePin(int pin) {
        this.pin = pin;
        if (pinChangeListener != null) {
            pinChangeListener.pinChanged();
        }
    }
}

要将回调/侦听器连接到信用卡,您只需要实现PinChangeListener方法:

creditCard.pinChangeListener = new PinChangeListener() {
    public void pinChanged() {
        System.out.println("The pin has been changed");
    }
};

类似地,当您将侦听器附加到按钮时,JVM 会检测到单击(您可能不想进入如何检测到单击!),并且附加的该侦听器的侦听器由 JVM 为您调用。希望这清除。actionPerformed()


答案 2

但是对此方法有一个特定的调用,只是它不是在你的代码中,而是在JVM中发生。按钮按下会引发内部事件,导致 JVM 告诉按钮通知其所有侦听器它已被按下。这将导致调用所有附加的操作Listener 的 actionPerform 方法。

要查看有关其工作原理的信息,请首先查看 AbstractButton 类的 Java API,您可以在其中找到该方法

protected void fireActionPerformed(ActionEvent event)

哪里

通知所有已对此事件类型发出通知感兴趣的侦听器。事件实例是使用事件参数延迟创建的。

然后,有关进一步的信息,您将需要超越Java API到源代码,可以在此处找到。如果你在那里查看Java 8.0源代码,然后查找javax,然后摆动,然后是AbstractButton,你会发现一种方法:fireActionPerformed(ActionEvent event)

2002    protected void More ...fireActionPerformed(ActionEvent event) {
2003        // Guaranteed to return a non-null array
2004        Object[] listeners = listenerList.getListenerList();
2005        ActionEvent e = null;
2006        // Process the listeners last to first, notifying
2007        // those that are interested in this event
2008        for (int i = listeners.length-2; i>=0; i-=2) {
2009            if (listeners[i]==ActionListener.class) {
2010                // Lazily create the event:
2011                if (e == null) {
2012                      String actionCommand = event.getActionCommand();
2013                      if(actionCommand == null) {
2014                         actionCommand = getActionCommand();
2015                      }
2016                      e = new ActionEvent(AbstractButton.this,
2017                                          ActionEvent.ACTION_PERFORMED,
2018                                          actionCommand,
2019                                          event.getWhen(),
2020                                          event.getModifiers());
2021                }
2022                ((ActionListener)listeners[i+1]).actionPerformed(e);
2023            }
2024        }
2025    }