简体   繁体   English

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

[英]action listeners and event sources in Swing

OK, so if I add an ActionListener to a GUI element, and it's the only element I use that ActionListener with, does it matter which of the following lines (a,b) I use to get the checkbox selected state? 好的,所以如果我将一个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);
        }
});

It makes sense to me that if I add the ActionListener object to multiple GUI elements, then I should use (b). 对我来说,如果我将ActionListener对象添加到多个GUI元素,那么我应该使用(b)。

And in (b), is it OK to blindly cast event.getSource() to JCheckBox , since I'm the one who added the action listener, or should I program defensively and do an instanceof check? 在(b)中,可以盲目地将event.getSource() JCheckBoxJCheckBox ,因为我是添加动作侦听器的人,或者我应该进行防御性编程并执行instanceof检查?

note: this question is in the context of event listeners in general; 注意:这个问题一般是在事件监听器的背景下; kdgregory has some good points below specifically re: checkboxes which I had neglected to consider. kdgregory有一些优点,特别是re:复选框,我忽略了考虑。

I'd do neither. 我什么都不做。

If clicking the checkbox is going to start some action, I'd attach an ItemListener , then just look at the selection state in the ItemEvent . 如果单击复选框将开始一些操作,我将附加一个ItemListener ,然后只查看ItemEvent中的选择状态。

However, checkboxes don't normally invoke actions, they manage state. 但是,复选框通常不会调用操作,它们会管理状态。 So a better approach is to examine all of your checkboxes in response to whatever does kick off the action. 因此,更好的方法是检查所有复选框,以响应启动操作的任何操作。


Edit: some commentary about the larger issues that the OP raised. 编辑:关于OP提出的更大问题的一些评论。

First, it's important to realize that large parts of Swing represent implementation convenience rather than a coherent behavior model. 首先,重要的是要认识到Swing的大部分代表实现的便利性而不是连贯的行为模型。 JCheckBox and JButton have nothing in common other than the fact that clicking within their space is meaningful. 除了在他们的空间内点击是有意义的事实之外, JCheckBoxJButton没有任何共同之处。 However, they both inherit from AbstractButton , which provides implementation details such as the button's label. 但是,它们都继承自AbstractButton ,后者提供了按钮标签等实现细节。 It also assumes that buttons are "pressed", and that pressing a button will initiate some meaningful behavior (the action). 它还假设按钮被“按下”,按下按钮将启动一些有意义的行为(动作)。 In the case of JCheckbox, however, the button press is not important, the change in state is. 但是,在JCheckbox的情况下,按下按钮并不重要,状态的变化是。 That state change is signaled to the ItemListener -- which is also defined on AbstractButton even though state changes are meaningless to other button types (the JavaDoc even says "checkbox"). 状态更改将发送到ItemListener - 它也在AbstractButton上定义,即使状态更改对其他按钮类型没有意义(JavaDoc甚至说“复选框”)。

One of the things that Swing did get right -- if hard to use -- is the idea of that an Action is separate from the control initiating that action. Swing确实做得正确的事情之一 - 如果难以使用 - 是一个动作与启动该动作的控制分开的想法。 An Action object can be invoked from multiple controls: a menu item, a pushbutton on a dialog, a keystroke, whatever. 可以从多个控件调用Action对象:菜单项,对话框上的按钮,击键等等。 More important from a design perspective is that it takes you away from the idea of a generic "listener" that tries to figure out what needs to happen. 从设计的角度来看,更重要的是它会让你远离想要找出需要发生什么的通用“听众”的想法。 I've seen apps where a single listener receives input from the entire menu system, for example, and then runs through a big if/else chain to figure out which menu item was pressed. 例如,我已经看过单个监听器从整个菜单系统接收输入的应用程序,然后通过一个大的if / else链来确定按下了哪个菜单项。 Using Actions means you have more classes, but in the long run gives you a more maintainable app. 使用Actions意味着你有更多的类,但从长远来看,它为你提供了一个更易于维护的应用程序。

Finally, from a usability perspective, there's a difference between controls that maintain state, such as JCheckbox and JTextArea, and those that initiate actions, such as JButton and JMenuItem. 最后,从可用性的角度来看,维护状态的控件(如JCheckbox和JTextArea)与启动操作的控件(如JButton和JMenuItem)之间存在差异。 I have seen a (web) app where clicking on a radio button takes you to a different page. 我看过一个(网络)应用程序,单击一个单选按钮会将您带到另一个页面。 That's bad. 那很糟。 Even if you're planning to use listeners internally, to update the state of some model, you should ask yourself why the collection of GUI elements do not in themselves provide you with a model. 即使您计划在内部使用侦听器,更新某些模型的状态,您也应该问问自己为什么GUI元素集合本身不会为您提供模型。

For the case where the listener is exclusive (such as an anon listener), I use (a). 对于监听器是独占的情况(例如匿名监听器),我使用(a)。

If the listener will be reused (eg, this is an instance of ActionListener) I'll write it as: 如果将重用侦听器(例如, this是ActionListener的一个实例),我将其写为:

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

If you have several checkboxes and they are processed the same way, then instanceof makes sense. 如果你有几个复选框,并且它们以相同的方式处理,那么instanceof是有意义的。

I'd program with b defensively as it's the best-practice option. 因为这是最好的练习选择,我会用b进行防守编程。 But if only you are ever going to use the code then there is no reason why you can't do a. 但是,如果只有你将要使用代码,那么没有理由你不能做。 However, imagine how happy you will be with yourself if you come back to it at some future point, change something and find you wrote good code which you can directly reuse... 但是,想象一下,如果你在未来的某个时刻回到它,改变一些东西并找到你编写好的代码,你可以直接重用它,你会对自己有多高兴...

in (b) to be rigourous, you should indeed do a instanceof check, but it's not that important. 在(b)要严格,你应该做一个检查的实例,但它并不重要。 I would think both these lines are fine and acceptable, though (b) would be "better code" 我认为这两条线路都很好并且可以接受,但是(b)将是“更好的代码”

Although, what is usually done in an action listener is simply call another method customized to your checkbox. 虽然,通常在动作侦听器中执行的操作只是调用为您的复选框自定义的另一种方法。 So it would look like something like this: 所以它看起来像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM