ItemListener vs ChangeListener vs ActionListener - java

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.

Related

Add actions to JPopupMenu options

I have a class that extends JPanel and implements MouseListener. In this class, if the panel is clicked the following two functions are executed:
#Override
public void mouseClicked(MouseEvent e) {
displayExitPopup();
}
private void displayExitPopup() {
JPopupMenu exitPopup = new JPopupMenu();
exitPopup.add("Exit Game");
exitPopup.add("Cancel");
exitPopup.show(this, this.getWidth(), this.getHeight());
}
This all works fine and the popup displays the 2 options as it should.
Now I am trying to perform actions when either of the two options in the popup menu are clicked - System.exit(0) if Exit Game is clicked, and the popup menu to close if Cancel is clicked. How can this be done?
If you take a look at the JavaDocs for JPopupMenu#add(String), you will find that it's a convenience method which returns a JMenuItem, you should then be able to add an ActionListener to it
Take a look at Bringing up a PopupMenu for more details
Having said that, I would instead, encourage you to make use the Action API which will allow you to create self contained units of work, which also provide the information needed to create the JMenuItem used by the JPopupMenu
Have a look at How to Use Actions for more details
You should also be using JComponent#setComponentPopupMenu instead of trying to use a MouseListener, as different platforms have different triggers for a popup menu and it's complicated and ugly real quick
When adding a item to JPopupMenu, you get a JMenuItem. On this object, you can call addActionListener to add a action listener, like you have with a JTextField or a JButton.
exitPopup.add("Cancel").addActionListener(e-> {
// do something
});

Difference between ChangeListener and ItemListener

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.

How to assign the enter key on my keyboard to a JButton

I have created a Jframe with a JButton for a specific action.
Now please I want a situation whereby anytime I hit my enter key on my keyboard it will perform the action I have coded in my Jbutton.
My Jframe was designed with Netbeans 7.3.
Now please I want a situation whereby anytime I hit my enter key on my keyboard it will perform the action I have coded in my Jbutton.
Make your JButton the default button of the JRootPane.
You do this by calling setDefaultButton(myJButton) on the root pane.
And you can get the JRootPane by calling getRootPane() on your JFrame.
Note that if you want this action when a JTextField has focus, then the solution is different; here you'll want to add the same ActionListener given to the JButton to the JTextField.
Implement ActionListener Interface
The listener interface for receiving action events. The class that is
interested in processing an action event implements this interface,
and the object created with that class is registered with a component,
using the component's addActionListener method. When the action event
occurs, that object's actionPerformed method is invoked.

Forcing a JPopupMenu to disable hover effects on its owner JFrame?

When i right click on a JTable in a JFrame I show a JPopupMenu. If I left this JPopupMenu shown as it is and moved with the mouse to the JTable I can still hover on its rows.
This is not the default behavior of Windows applications. In normal case if a popup menu appears in a program it blocks any hover actions on the popup owner window.
Can i do the same thing in Java ?
One way to approach this problem is to set an instance variable in one of your GUI elements to flag whether or not to enable hover events. I have shown below how this may work, but it's not in its complete form, you will also need to re-enable hover when the JPopupMenu is dismissed, and also check the state of the ENABLE_HOVER field before firing hover effects.
public MyTable extends JTable {
private boolean ENABLE_HOVER = true;
public MyTable() {
...
this.addMouseListener(new MouseListener(){
...
public void mouseClicked(MouseEvent e) {
if (isRightClick(e)) {
setHoverEnabled(false);
showJPopupMenu();
}
}
});
}
protected void setHoverEnabled(final boolean hover) {
this.ENABLE_HOVER = hover;
}
}
Another method which may be better suited to disabling multitudes of however enabled elements is to intercept the events at the glass pane. An example of how this might work is shown here. Be warned though if your interface is already built it may require significant re-jigging of your component classes.
You will need to intercept all events at the glass pane, if hover is enabled (no popup menu shown) you would pass the event to the appropriate component. Otherwise if hover is disabled and the MouseEvent occurred over the JPopupMenu is passed only to the JPopupMenu.

itemStateChanged on JButton

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.

Categories