5

我刚开始学习如何使用动作监听器。据我了解,它的工作方式如下:

  1. 有一些类默认包含“addActionListener”方法(例如按钮类)。

  2. 使用此方法,我们将动作侦听器添加到对象。例如:listenedObject.addActionListener(listeningObject)

  3. 当执行带有“listenedObject”的动作时,将调用“listeningObject”的“actionPerformed”方法。因此,这意味着当我们为 listenerObject 编写一个类时,我们需要在其中放置“actionPerformed”方法。

我不清楚的是,我们是否应该为我们想要收听的每个对象创建一个新类。在我看来,这不是一个优雅的解决方案。另一方面,如果我们为所有(或至少许多)对象有一个动作侦听器类,那么我们就会遇到问题,因为此类的实例将不知道哪个对象正在调用“actionPerformed”方法(我们需要知道因为 actionPerformed 执行的操作因调用此方法的人员而异)。

在我看来,对于我们需要创建的每个监听对象都是“个人”动作监听器,我们可以通过为动作监听器的相应字段设置特定值来做到这一点。但我不确定这是一种标准的方式吗?人们通常是怎么做的?

4

6 回答 6

9

处理这个问题的最常见方法 - 从我自己的个人经验来看 - 是简单地创建一个匿名内联类。像这样:

listenedObject.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
        // Your action handling code in here
    }
});

我经常看到人们调用包含listenedObject 的对象的方法。例如,在具有按钮的 Dialog 中:

myOkayButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
        okayButtonPressed();
    }
});

然后稍后在对话框类中:

private void okayButtonPressed() {
    // Do what we need to do
}
于 2010-03-12T16:58:58.470 回答
2

个人而言,如果可能的话,我更喜欢使用Action类(例如 的子类AbstractAction)而不是简单地依赖于动作监听器。这样,我可以为原始小部件提供名称、图标、工具提示等...

于 2010-03-12T17:01:36.903 回答
2

我一直觉得有用的方法(用于导航目的)是创建一个匿名内部类,然后委托给外部类:

listenedObject.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
        listenedObject_actionPerformed(evt);
    }
});


private void listenedObject_actionPerformed(ActionEvent evt) {
    //Your handling goes here
}

然后,使用结构查找(IDEA 中的 CTRL+F12,Eclipse 中的 CTRL+O)在 IDE 中获取处理代码要容易得多。

使用单个类(如 GUI MyCoolPanel)作为其一组组件(按钮等)的公共侦听器的问题在于,该actionPerformed方法随后进行了很多丑陋的if-else比较来确定实际按下了哪个按钮- 不是很OO一点也不!

你当然不应该过分担心这种事情的性能方面——它们可能在极端情况下可以忽略不计!过早的优化是出了名的坏事

于 2010-03-12T17:02:21.053 回答
1

我一直觉得有用的方法是创建一个单独的类,该类实现 ActionListener 接口和执行操作所需的所有其他方法。这样,动作就不会与特定对象绑定,并且可以从按钮、菜单等触发。我猜有点像命令模式。它使代码保持简单。

匿名类不可重用。

重定向到包含 listeneredObject 的对象会导致难以维护的巨大类。

于 2010-03-12T17:36:54.693 回答
0

请注意方法 removeActionListener 的存在是有原因的。如果您侦听的对象将与处理事件的对象一起死亡,您可以跳过侦听器清理。但是,如果您的组件侦听从外部源提供的模型,您应该在 addNotify 中添加您的侦听器并在 removeNotify 方法中删除它们。否则你可能会有内存泄漏。

于 2010-03-12T17:16:04.927 回答
0

也许现在不是真的,但我相信在最近的将来(Java 7 发布之后)这样的事情将是常见的方式:

listenedObject.addActionListener ( #{doSmth();} );
于 2010-03-12T17:21:44.293 回答