I have menu items with an accelerators. I would like to detect when a menu item was clicked as opposed to executed using accelerator. Is this possible?
Thanks,
Alexander.
While you can listen for MouseEVents and Actions, you can also just inspect the modifiers of the ActionEvent and see if a key was involved in the event or not. That way, you only have one listener to deal with...
a mouse click will fire off a MouseEvent and an Action. An accelerator will only fire off an action.
You can compare the key-info in the ActionEvent with the Action#ACCELERATOR_KEY key-value pair, which should be able to distinguish between a user clicking while holding a random/modifier key, and the actual accelerator key combination
Related
I have a Swing application and I need to make a specific action if an alphanumeric key is pressed during a mouse drag action.
I successfuly managed the drag action but I can't get the key pressed.
It seems that only the modifiers (alt, ctrl, shift) are available in a mouse event?
Is there a a way to know if for example the W key is pressed in a java.awt.event.MouseAdapter method (without adding a keyListener) ?
Is there a a way to know if for example the W key is pressed in a java.awt.event.MouseAdapter method (without adding a keyListener) ?
No, you need to use a KeyListener.
And you also need to reverse your logic. That is when you handle the KeyEvent you need to check if the mouse is also being used by looking at the "modifiers" of the KeyEvent. Read the API for more information on the getModifiersEx() method.
I am starting to write some code in Java Swing and I am getting a little bit mixed up in the hierarchy of listeners that swing offers. Namely I wanted to know when to use, for instance, an ActionListener over ListSelectionListener and how to differentiate when a particular listener gets called from the UI i.e. after what user interaction.
Thanks very much for your responses.
About ActionListener
An action event occurs, whenever an action is performed by the user.
Examples: When the user clicks a button, chooses a menu item, presses
Enter in a text field. The result is that an actionPerformed message
is sent to all action listeners that are registered on the relevant
component. reference
About ListSelectionListener
List selection events occur when the selection in a list or table is
either changing or has just changed. List selection events are fired
from an object that implements the ListSelectionModel interface. To
get a table's list selection model object, you can use either
getSelectionModel method or getColumnModel().getSelectionModel(). reference
Q. how to differentiate when a particular listener gets called from the UI i.e. after what user interaction.
The above details and the references contains much information to get start with.
ActionListener is used e.g. for JButton, it tells just that the GUI-element has done something (a button can not do anything except be clicked).
ListSelectionListener contains more information (which element has been choosen).
For more information on when to use which Listener check the javadoc of the element you want to use.
I have a MenuItem with a shortcut key to save the data of a JTextFied temporary and print it
The save function is called on FocusLost event of the JTextField and the print is called via MenuItems actionListener and is fired when I click on the MenuItem as well as when i press the shortcut key for the menuitem (eg: f1)
The problem is that when i directly press f1(shortcut for menuitem), the focusLost event for the Textfied is fired only after the menuitem has performed its action, whereas when I go to the menu and press, the focuslost is fired first followed by the menu's Action
Is there a way to force a Focuslost so that even with a shortcut key, the focusLost event is fired first
Tried using requesfocusinWindow, setText (performed on other demo textfields just to force a focusLost)
1) I think that's not possible in Programing Languages, more about that in the theory of AWT Focus Subsystem and How to Use the Focus Subsystem,
2) you have to redirect this Save Processes to the Backgroung Task, and before that you can check if JMenu and its JMenuItem are/aren't selected, for this check use only ButtonModel, otherwise don't do that, because your GUI heve to waiting for this processes
3) anothere choice is save on periodical bases values from JComponents to some Array, there you can check if value was/were changed, all changes must be checked/saved from Backgroung Task, without any impact to the Swing GUI
4) easiest way how to create something as Timer would be to wrap some logics to the Runnable#Thread, delayed by Thread.sleep(int) but exclusively inside Runnable#Thread only
It is generally suspect when you want to 'force' focusLost, as the intention of that event is the user did something to change the focus status of the application. When you say that F1 is a menu item shortcut, do you mean it is a shortcut to the same code that is executed when the menu is selected, or that you have it setup as a menu mnemonic?
In the end, shortcut keys do not generally change focus intrinsically, whereas the mouse actions required to click a menu item do, and that is something you may have to account for yourself.
I'm looking for a listener that fires ONLY when the user, the one who's using the program, selects an item in the JComboBox. I don't want to use ActionListener or ItemListener because those also fire when I select an item through the program. And I can't use MouseListener either because it only fires when I click the JComboBox, not when I select an item.
I was wondering what the easiest way to do this is? Currently, my solution is messy. When I change the selected item of the jcombobox through code, I set a flag to true. And in my action listener, it only executes if the flag is false.
A) I would recommend you to temporarily remove the listener when you perform the selection programatically.
B) If your programatic change is not an effect of another GUI event you could solve it the following ugly/non-robust/error-prone/"hacky" way: Check EventQueue.isEventDispatchThread() to find out if the click was triggered by the GUI thread (the user).
C) (Oops I just reread your question and saw that you've already discovered the method described below. Basically I would say that this (or the the method described above) is your best alternative.)
Another option is to have a boolean flag called something like nonUserSelection which you set to true before you select a value programatically and reset to false afterwards. In the action listener you simply add an
if (nonUserSelection)
return;
I've a problem with setAccelerator(). Right now, I have the code that works for Ctrl+X for DELETE operation. I want to set the accelerator to Shift+Delete as well for same JMenuItem.
My code as follows:
JMenuItem item = new JMenuItem(menuText);
item.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_X, KeyEvent.CTRL_MASK));
item.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_DELETE, KeyEvent.SHIFT_MASK));
but this is working only for Shift+Delete operation. Seems it is overriding the Ctrl+X operation. Can we make both these keystrokes work at the same time?
Please guide.
Yes it can be done. Behind the scenes the setAccelerator() is just creating a Key Binding, however as you noticed the second binding replaces the first.
So, you need to create an Action (not an ActionListener) to add the to the menu item. Read the section from the Swing tutorial on How to Use Actions for more information. Now that you have created the Action, you can share the Action with another KeyStroke by manually creating a Key Binding. You can read the section from the Swing tutorial on How to Use Key Bindings for a detailed explanation. Or you can read my blog on Key Bindings which give some simple code examples.
This second binding will not show up on the menu item itself.
From: http://java.sun.com/j2se/1.4.2/docs/api/java/awt/AWTEvent.html
The masks are also used to specify to which types of events an AWTEventListener should listen.
So you can combine the mask for two keys, but not the KeyEvents.
item.setAccelerator(
KeyStroke.getKeyStroke(
KeyEvent.VK_X, KeyEvent.CTRL_MASK + KeyEvent.SHIFT_MASK));
A workaround solution would be to catch the KeyEvent in the middle (after your component fired it, but before your listeners will act on it) and check, whether its one of the two combinations. Then fire one event, on which you programmatically agree to represent the action you wanted.
The second call indeed overrides the accelerator. If the method starts with set, there will be only one. If the method starts with add, you can have more than one (for example for a number of listeners).
If you want multiple keystrokes to do the same, I think you should add a keyListener to the top frame (or panel, dialog, ...) which invokes the action listeners added to the menuItem.