Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Swing中的动作侦听器和事件源_Java_Swing_Actionlistener - Fatal编程技术网

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

Java Swing中的动作侦听器和事件源,java,swing,actionlistener,Java,Swing,Actionlistener,好的,那么如果我向GUI元素添加一个ActionListener,并且它是我使用该ActionListener的唯一元素,那么我使用以下哪一行(a,b)来获取复选框选中状态是否重要 final JCheckBox checkbox = (JCheckBox)this.buildResult.get("cbDebugTick"); checkbox.addActionListener(new ActionListener() { @Override public void actionPe

好的,那么如果我向GUI元素添加一个
ActionListener
,并且它是我使用该
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
检查


注意:这个问题一般是在事件听众的背景下提出的;KDGRGGORY有一些优点,特别是RE:我忽略了的复选框。

< P>我会用B防御程序,因为这是最佳实践选项。但是如果你只打算使用代码,那么你没有理由不去做一件事。然而,想象一下,如果你在将来某个时候回到它,改变一些东西,发现你编写了可以直接重用的好代码,你会对自己感到多么高兴…

在(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)
}
我两个都不愿意

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

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


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

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

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


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

对于侦听器是独占的(例如anon侦听器),我使用(a)

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

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

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

没错,但可能会有另一个人通过谷歌发现这个问题,并且更愿意适当地使用API,而不是担心两种黑客中哪一种“更好”。这是公平的,我会在问题中注意到这一点+最后的另一条评论是:在本例中,我使用监听器将复选框状态传播到一个不了解复选框的模型对象,我想我应该使用javax.swing.JToggleButton.ToggleButtonModel而不是事件监听器;我以前在活动听众中遇到过这个问题,我想知道适当的良好做法。你能详细说明一下吗?如果可以访问匿名内部类中的相同方法/字段,为什么要转发到外部类?通过这种方式,您可以轻松地将不同组件添加到同一操作侦听器中,并以不同的方式和/或多态性处理它们,使代码“更好”,我不同意david的断言。像这样转发调用违背了去耦合的粒度(这就是为什么Swing中的事件通知首先采用侦听器方法)。理想的情况是,您可以完全分解动作行为,并在包含控件的视图外部使用动作侦听器——在这种情况下,选项(b)是首选技术。也就是说,您真正应该做的是创建一个操作并将控件附加到该操作。仅供参考,这是大多数IDE在使用GRPAHIC GUI创建者(例如NetBeans)时生成自动代码的方式