Swing中的动作侦听器和事件源

时间:2009-08-13 19:17:50

标签: java swing actionlistener

好的,所以如果我将一个ActionListener添加到一个GUI元素,并且它是 only 元素我使用ActionListener,那么下列哪一行是否重要(a,b)我用来获取复选框选中状态吗?

final JCheckBox checkbox = (JCheckBox)this.buildResult.get("cbDebugTick");
checkbox.addActionListener(new ActionListener() {
    @Override public void actionPerformed(ActionEvent event){               
            boolean bChecked =
            // (a) checkbox.isSelected();
            // (b) ((JCheckBox)event.getSource()).isSelected();
            model.setPrintDebugOn(bChecked);
        }
});

对我来说,如果我将ActionListener对象添加到多个GUI元素,那么我应该使用(b)。

在(b)中,可以盲目地将event.getSource()投射到JCheckBox,因为我是添加动作监听器的人,或者我应该采取防御性编程并执行{{1}检查?

注意:这个问题一般是在事件监听器的上下文中; kdgregory有一些优点,特别是re:复选框,我忽略了考虑。

4 个答案:

答案 0 :(得分:3)

我不会这样做。

如果点击该复选框即可开始执行某项操作,我会附加ItemListener,然后查看ItemEvent中的选择状态。

但是,复选框通常不会调用操作,它们会管理状态。因此,更好的方法是检查所有复选框,以响应启动操作的任何内容。


编辑:对OP提出的更大问题的一些评论。

首先,重要的是要认识到Swing的大部分代表了实现的便利而不是连贯的行为模型。 JCheckBoxJButton除了在其空间内点击有意义之外没有任何共同之处。但是,它们都继承自AbstractButton,它提供了实现细节,例如按钮的标签。它还假设按钮被“按下”,按下按钮将启动一些有意义的行为(动作)。但是,在JCheckbox的情况下,按下按钮并不重要,状态的变化是。状态更改发送到ItemListener - 它也在AbstractButton上定义,即使状态更改对其他按钮类型没有意义(JavaDoc甚至说“复选框”)。

Swing确实做对的事情之一 - 如果难以使用 - 就是Action与启动该行动的控制分开的想法。可以从多个控件调用Action对象:菜单项,对话框上的按钮,击键等等。从设计的角度来看,更重要的是它会让你远离想要找出需要发生什么的通用“听众”的想法。例如,我已经看过单个监听器从整个菜单系统接收输入的应用程序,然后通过一个大的if / else链来确定按下了哪个菜单项。使用Actions意味着你有更多的类,但从长远来看,它为你提供了一个更易于维护的应用程序。

最后,从可用性的角度来看,维护状态的控件(如JCheckbox和JTextArea)与启动操作的控件(如JButton和JMenuItem)之间存在差异。我看过一个(网络)应用程序,单击一个单选按钮会将您带到另一个页面。那很糟。即使您计划在内部使用侦听器,更新某些模型的状态,您也应该问问自己为什么GUI元素集合本身不会为您提供模型。

答案 1 :(得分:1)

对于监听器是独占的情况(例如匿名监听器),我使用(a)。

如果将重用侦听器(例如, this 是ActionListener的一个实例),我将把它写成:

@Override
public void actionPerformed(ActionEvent event) {
    Object src = event.getSource();
    if (src == checkbox) {
        boolean bChecked = checkbox.isSelected();
        // ...
    }
}

如果您有多个复选框,并且处理方式相同,那么instanceof就有意义了。

答案 2 :(得分:0)

我会用b进行防守编程,因为这是最佳练习选项。但是,如果只有你将要使用代码,那么没有理由你不能做。但是,想象一下,如果你在未来的某个时候回到它,改变一些事情并找到你可以直接重用的好代码,你会对自己有多高兴...

答案 3 :(得分:0)

在(b)中要严谨,你应该做一个检查实例,但这并不重要。我认为这两条线都很好并且可以接受,但(b)将是“更好的代码”

尽管通常在动作侦听器中执行的操作只是调用另一个为您的复选框自定义的方法。所以它看起来像这样:

 @Override public void actionPerformed(ActionEvent event) {                                  
    //your treatment would be in this method, where it would be acceptable to use (a)                  
    onCheckBoxActionPerformed(event)
}