如果没有显式调用'actionPerformed'方法怎么调用呢?

时间:2014-08-31 12:46:39

标签: java swing events user-interface methods

我刚刚开始使用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!");
  }
}

在引发某个方法之前,不应该为某个类创建一个对象(静态方法除外)?

单击该按钮时,会调用actionPerformed方法,但如何?电话在哪里?我已经实现了接口ActionListener,但代码在哪里知道动作何时发生' ActionEvent'对象应该发送到' actionPerformed'方法?它出现在Button类中吗? Button类中是否存在addActionListener方法?

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

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

2 个答案:

答案 0 :(得分:11)

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

在这里,您注册的听众, 就是这样,

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会检测到单击,(您可能不想进入检测到单击的方式!)和该监听器的actionPerformed()附件由JVM为您调用。希望这清楚。

答案 1 :(得分:4)

但是对这种方法有一个特定的调用,只是它没有出现在你的代码中,而是出现在JVM中。按钮推动启动内部事件,引导JVM告诉按钮通知其所有侦听器已被推送。这将导致调用所有附加的ActionListener的actionPerformed方法。

要查看有关其工作原理的信息,请先查看您将找到方法的Java API for the AbstractButton class

protected void fireActionPerformed(ActionEvent event)

其中

  

通知所有已注册对此事件类型的通知感兴趣的听众。使用event参数延迟创建事件实例。

然后,为了获得更多信息,您需要超越Java API,找到可以找到here的源代码。如果你在那里查看Java 8.0源代码,然后查找javax然后swing,然后是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    }