Swing action listeners and event sources

OK, therefore, if I add an ActionListener element to the GUI element, and this is the only element I use this ActionListener with, it matters which of the following lines (a, b) I use to check the selected state box?

 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 seems to me that if I add an ActionListener object to several GUI elements, then I should use (b).

And in (b), is it normal to blindly drop event.getSource() in the JCheckBox , since I'm the one who added an action listener, or do I need to program protection and perform instanceof checking?

Note: this question occurs in the context of listeners of events in general; The kdgregory has a few good points below specifically re: checkboxes, which I neglected considering.

+4
source share
4 answers

in (b) to be strict, you really need to do an instance check, but that is not so important. I would think that both of these lines are accurate and acceptable, although (b) would be "better code"

Although, what is usually done in the action listener is simply called by another method configured to your checkbox. So it will look 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) } 
0
source

I would also.

If clicking on the checkbox starts some action, I will add an ItemListener , and then just look at the selection state in the ItemEvent .

However, flags, as a rule, do not cause actions; they control the state. Therefore, it is best to consider all of your checkboxes in response to everything that starts with an action.


Edit: some comments about the larger issues raised by the OP.

First, it’s important to understand that large parts of Swing are usability, not a model of consistent behavior. JCheckBox and JButton have nothing ordinary than the fact that clicking in their space makes sense. However, they both inherit from AbstractButton , which provides implementation details such as a button shortcut. It also assumes that the buttons are “pressed” and that pressing the button initiates some meaningful behavior (action). However, in the case of JCheckbox, pressing a button does not matter, a change of state. This state change is signaled by an ItemListener, which is also defined in AbstractButton, although state changes do not make sense for other types of buttons (JavaDoc even says "checkbox").

One of the things Swing did right — if it's hard to use — is the idea that the Action is separate from the control that triggers the action. An Action object can be called up from several controls: a menu item, a button in a dialog box, a keystroke, anything. More important from a design point of view is that it takes you away from the idea of ​​a general “listener” who is trying to figure out what is going to happen. I saw applications in which one listener receives input from the entire menu system, for example, and then goes through a large if / else chain to find out which menu item was clicked. Using "Actions" means you have more classes, but ultimately gives you a more convenient application.

Finally, in terms of usability, there is a difference between controls that support state, such as JCheckbox and JTextArea, and those that trigger actions, such as JButton and JMenuItem. I saw an application (web application) in which clicking on the switch takes you to another page. This is bad. Even if you plan to use internal listeners to update the state of a model, you should ask yourself why the collection of GUI elements alone does not provide you with a model.

+3
source

In the case where the listener is exclusive (e.g. the listener for announcements), I use (a).

If the listener will be reused (for example, this is an instance of ActionListener), I will write it as:

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

If you have multiple checkboxes and they are handled the same way, then instanceof makes sense.

+1
source

I would program defensively with b, as this is the best option. But if you ever use the code, then there is no reason why you cannot do it. However, imagine how happy you are with yourself if you return to it at some point, change something and find that you have written good code that can be used directly ...

0
source

All Articles