4

好的,所以如果我将 an 添加ActionListener到 GUI 元素,并且它是我使用它的唯一元素,我使用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,因为我是添加动作侦听器的人,还是应该进行防御性编程并进行instanceof检查?

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

4

4 回答 4

3

我都不会。

如果单击复选框将开始一些操作,我会附加一个ItemListener,然后只需查看ItemEvent中的选择状态。

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


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

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

Swing 做对的一件事——如果难以使用的话——是动作与启动该动作的控件是分开的。可以从多个控件调用 Action 对象:菜单项、对话框上的按钮、击键等等。从设计的角度来看,更重要的是,它使您摆脱了试图找出需要发生什么的通用“侦听器”的想法。例如,我见过一个应用程序,其中单个侦听器接收来自整个菜单系统的输入,然后运行一个大的 if/else 链来确定按下了哪个菜单项。使用 Actions 意味着你有更多的类,但从长远来看,它会给你一个更易于维护的应用程序。

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

于 2009-08-13T20:41:29.597 回答
1

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

如果监听器将被重用(例如,this是 ActionListener 的一个实例),我会将其写为:

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

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

于 2009-08-13T20:57:50.043 回答
0

我会用 b 进行防御性编程,因为它是最佳实践选项。但是,如果只有您打算使用该代码,那么您就没有理由不这样做。然而,想象一下,如果你在未来某个时候回到它,改变一些东西并发现你编写了可以直接重用的好代码,你会对自己感到多么高兴......

于 2009-08-13T19:22:07.057 回答
0

在 (b) 中,为了严谨起见,您确实应该进行 instanceof 检查,但这并不重要。我认为这两行都很好并且可以接受,尽管 (b) 将是“更好的代码”

虽然,通常在动作侦听器中所做的只是调用为您的复选框定制的另一个方法。所以它看起来像这样:

 @Override public void actionPerformed(ActionEvent event) {                                  
    //your treatment would be in this method, where it would be acceptable to use (a)                  
    onCheckBoxActionPerformed(event)
}
于 2009-08-13T19:24:46.130 回答