What is the difference between ChangeListener and ItemListener for JCheckBox and JRadioButton? Both of them work fine when they are selected/deselected.
I know that some components doesn't support ChangeListener like the JComboBox. Other than the reason that ChangeListener or ItemListener work for only some components. Is there any difference between them like when are they generated?
Any answer is appreciated. Thanks in advance.
both listeners for JCheckBox work similarly in that both will fire event upon change in state, whether by clicking or toggle by spacebar or programmatically through doClick() method (Similar to mouse click). One major difference though is that JCheckBox’s itemListener can be fired through setSelected(boolean) method which allows one to fire the event based on desired state whereas others will act only after the state is altered. So why is it important ? Consider when application startup, the GUI needed to configure for defined state, and using setSelected will trigger ItemListener. Note that setSelected is exclusive to ItemListener and has no effect on ActionListener. Do not register both ActionListener and ItemListener as both will be fired, landing the component in a random state
ChangeListener is notyfied when there's any change to the button state. ChangeListener is not notified of what has changed, only that the object has changed. Item listener is only notyfied when an item is selected; by user or setSelected method. It's also not true that ChangeListener is not notyfied when setSelected method is invoked. It is the change of the object state.
Related
I've seen many Java Swing programs that use ActionListener, ChangeListener, or ItemListener. What are the differences between these and when should I use each one?
ActionListener
They are used with buttons or menu. So that whenever you click them it notifies the ActionEvent which in turn invokes the actionPreformed(ActionEvent e) function to perform the specified task.
ItemListeners
These are used with checkboxes, radio buttons, combo boxes kinds of stuff.
See what happens when you use ActionListener with combo box instead of item listener in this link https://coderanch.com/t/331788/java/add-listener-combo-drop-list.
ChangeListener
This is used with components like sliders, color choosers and spinners where you want the action to be performed according to the change in that component (https://docs.oracle.com/javase/tutorial/uiswing/events/changelistener.html). Focus on the word "change". Then you might think it should work with buttons too. You can see for yourself on this website http://www.java2s.com/Tutorial/Java/0240__Swing/AddchangelistenertoButtonmodel.htm
For a JMenuItem, instead of a listener, you should use an Action (which is a more capable form of ActionListener):
Action saveAction = new AbstractAction("Save") {
#Override
public void actionPerformed(ActionEvent event) {
saveDocument();
}
};
saveAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
saveAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control S"));
saveMenuItem = new JMenuItem(saveAction);
For JCheckBoxMenuItems and JRadioButtonMenuItems, just as with regular JMenuItems, the Action’s actionPerformed method is called when the user activates the menu item. You can check the new state from within your Action:
Action showStatusAction = new AbstractAction("Show Status") {
#Override
public void actionPerformed(ActionEvent event) {
boolean selected = (Boolean) getValue(SELECTED_KEY);
statusBar.setVisible(selected);
}
};
showStatusAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_W);
showStatusAction.putValue(Action.SELECTED_KEY, true);
showStatusMenuItem = new JCheckBoxMenuItem(showStatusAction);
Note that Action.SELECTED_KEY only works if you set it to true or false before you install the Action. From the documentation:
Components that honor this property only use the value if it is non-null. For example, if you set an Action that has a null value for SELECTED_KEY on a JToggleButton, the JToggleButton will not update its selected state in any way. Similarly, any time the JToggleButton's selected state changes it will only set the value back on the Action if the Action has a non-null value for SELECTED_KEY.
If you insist on using listeners directly, ItemListener indicates selection state, so it can be used to monitor the state of JCheckBoxMenuItems and JRadioButtonMenuItems. For all other JMenuItems, use ActionListener.
The above actually applies to all descendants of AbstractButton as well as JMenuItem and its descendant classes:
For JButtons, use an Action.
For JToggleButtons, JCheckBoxes, and JRadioButtons, use an Action and check its SELECTED_KEY value.
If you aren’t willing to use Actions, use ActionListener for JButtons, and use ItemListener for JToggleButtons, JCheckBoxes, and JRadioButtons.
My understanding is that there is no reason to use a ChangeListener with a standard JMenuItem or button, as a ChangeEvent is mainly intended to indicate to renderers that the component needs to be repainted.
My program has the ability to change the selected item of my combobox. But how can I know if the item change has been caused by an human mouse click on the item itself or by my program.
I'm pretty much looking for a MouseListener that can be added to the items of the JComboBox and not the JComboBox itself.
A JComboBox is a compound component, and it is highly recommended that you avoid using low-level listeners such as a MouseListener with it. Instead why don't you disable your selection listener (perhaps you're using an ActionListener) when the code selects an item, and then re-enable it after the selection is done. Thus you'll know that any activity by the ActionListener is from a user's choice. You can disable and enable the listener by either removing and re-adding it, or by giving using a boolean variable that allows the listener to react only when the boolean is true.
I read that a JButton implements ItemSelectable and into documentation it has the method addItemListener so I can argue that it can generate an ItemEvent... but when I register with a JButton (but also for a JMenuItem) that interface the event is not rised?
Why?
I understand that if into docs is reported that a component has an add....Listener it means that it support that event... but for experience isn't often so...
What's the truth?
There is a difference between a button being "pressed" (which fires an ActionEvent) and a button being "selected" (which fires the ItemEvent). By default a JButton is backed by a javax.swing.DefaultButtonModel. If you look at the setPressed and setSelected methods in default button model you'll see the code that fires the different events.
So if you programmically call JButton.setSelected, your item listener will be fired. If you click the button, you'll only get the action event.
Note also that with a JButton (unlike, say, a JToggleButton) you probably won't see much visually when it is selected.
I have JTextField with FocusListener that call textfield.grabFocus() every time when textfield lose focus. But unfortunetly, it allow parent Window to react on user action. Is there any way to don't give the focus to the Window using only JTextField methods?
If I'm understanding you correctly, you don't want any other controls on your program to be usable while this field requires focus. The problem is, each object is likely to have at least one event listener waiting for some action to occur, and stealing your focus away from you.
You can make all objects not focusable by setting setFocusable(false) for each object, but that will still allow events to be captured.
I'd override/replace (or possibly completely remove, if really necessary) the event listeners on all the other objects to only perform actions when the proper conditions are met (when your object doesn't require focus, if that would ever occur). If overridden/replaced, each listener could then return focus to the JTextField if those conditions are not met.
Also, it is better to use requestFocus() or requestFocusInWindow() instead of grabFocus(). See JComponent grabFocus() and JComponent requestFocus() for more information.
Can you disable a JButton without graying out the button itself?
When you use setEnbaled(false), the button disables and turns to gray. Is it possible to disable the button but make the appearance of the button still the same?
You could ignore the button press in your ActionListener if a flag is set; however, you should not disable the button without showing it as disabled: it will only confuse the users of your application.
I suggest setting a ButtonModel with overridden setArmed and setPressed. Exactly how you override it depends on exactly what you want it to do - should it appear to be pressed when pressed, for instance? Only set the ButtonModel once for a JButton. Add or repurpose state on the ButtonModel to indicate how you want it o behave at any given moment.
Clearly, GUIs with non-standard behaviour are likely to confuse users.