Key Bindings Fire Multiple Times when Holding Key - java

I'm following this guide to get key binding to work in my application. So far, the key bindings fire successfully, when I press a key. What I expect to happen is when I bind one action to a key pressed event and another action to a key released event, it will fire the first action when the key is pressed down and the second action when the key is released. What actually happens when I hold down a key is both actions get called multiple times. What can I do to achieve my desired behavior?
Here's how I'm implementing the key bindings:
component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("pressed UP"), "pressedUP");
component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released UP"), "releasedUP");
Action pressedUpAction = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("Pressed UP");
}
};
Action releasedUpAction = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("Released UP");
}
};
component.getActionMap().put("pressedUP", pressedUpAction);
component.getActionMap().put("releasedUP", releasedUpAction);
When I run the program, the output I actually get when I hold down the up key is Pressed UP, a slight pause, and then multiple Pressed UP values. When I release the up key, I get a Released UP message. The entire output looks like this:
Pressed UP
Pressed UP
Pressed UP
Pressed UP
Pressed UP
Pressed UP
Pressed UP
Released UP
The really weird thing is if I replace UP with a keyboard letter key, such as P, everything works as I expect it to.

use Boolean value inside Swing Action when once times fired events then change Boolean from false to true or vice versa
I'm sorry nobody knows how did you implemented KeyBindings, post an SSCCE

Related

JList remove selected items on keystroke and click

My task is to enable removing Jlist selected elements when alt is pressed and jlist is clicked. I did this by adding mouse listener to my jlist:
list.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e) {
java.util.List selectedItems = list.getSelectedValuesList();
if (e.isAltDown()){
for (Object o : selectedItems){
cm.removeElement(o); //cm is my custom model
}
}
}
});
My issue is that when there are two elements selected and I click the list with alt pressed only nearest element gets selected and is removed then. I have no clue how to remove several elements with this input combination.
The problem is that the mouse click clears all the previous selections and then selects the row you just clicked on. So therefore only that row is deleted.
So instead you should be handling a "right mouse" click and then use the right mouse button only for the deletion of the item.
if (e.isAltDown() && SwingUtilities.isRightMouseButton(e)) {
Or if you really want to do this on a left mouse click then you would probably need to use a ListSelectionListener. Every time the selection changes you would need to use the getSelectedValuesList() method and save the List returned from the method. Then in the MouseListener you would access the saved List instead of getting the currently selected List of items.
I don't like this approach because the logic is now contained in two separate listeners. Although I guess you could create a class that implement both the selection listener and the mouse listener.
This is not a perfect answer. But it solves the issue.
I just tried to see how the selection event works. When he selection happens an Mouse pressed event is triggered and then the Selection happens. So the MouseListeners which are already added to the component are responsible to make the selection. Removing the MouseListeners which are already in place would prevent the selection happen using mouse. So i did this.
MouseListener[] adapters = list.getMouseListeners();
for (int i = 0; i < adapters.length; i++) {
list.removeMouseListener(adapters[i]);
}
Now user will not be able to do the selection using mouse but he will be make the selection using keyboard. So the below would work.
list.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
java.util.List selectedItems = list.getSelectedValuesList();
if (e.isAltDown()){
for (Object o : selectedItems){
model.removeElement(o); //cm is my custom model
}
}
}
});
I think the answer given by camickr, should be followed.

Remove Enter key binding in JTable

What is the simplest and fastest way to remove the standard enter key bindings (pressing enter selects the next row) in a JTable?
That's what I tried
table.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), null);
But it doesn't work. I assume that we have to do that somehow for each cell and not the table itself.
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT and JComponent.WHEN_IN_FOCUSED_WINDOW have a value for the enter keystroke. So you want to get both of them
Correction: You need to get the InputMap for WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
InputMap iMap1 =
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
//InputMap iMap2 =
// table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
Then you want to set the value for the map to "none", instead of null, as described in How to Use Key Bindings.
To make a component ignore a key that it normally responds to, you can use the special action name "none". For example, the following code makes a component ignore the F2 key.
component.getInputMap().put(KeyStroke.getKeyStroke("F2"), "none");
So just do:
KeyStroke stroke = KeyStroke.getKeyStroke("ENTER");
iMap1.put(stroke, "none");
//iMap2.put(stroke, "none");
Also note when you just do getInputMap() without any arguments, it's basically the same thing as getInputMap(JComponent.WHEN_FOCUSED). And in the case of JTable, there's no value for the enter keystroke for that InputMap.
Read more at How to Use Key Bindings. You'll get a better explanation of the different InputMaps
UPDATE : Correction (corrections made above either struck through or // commented out)
You only to set it for the InputMap for JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
UPDATE per the OP comment: Yes in short
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.‌​getKeyStroke("ENTER"), "none");
This seems to be the most convenient way:
table.registerKeyboardAction(
null,
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
);
To assign an action replace null with ActionListener call or with e -> someMethod() for JDK 1.8
Update:
David Kroukamp solution:
private void createKeybindings(JTable table) {
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter");
table.getActionMap().put("Enter", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {}
});
}
And for you should be enough:
table.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter");
table.getActionMap().put("Enter",null);
I dont know if it is possible to use null, you could use anonymous class instead...

java key pressed to perform an action

i am very new to java.I am developing a inventory management system where i want to add the data to the jtable when "ENTER" key is pressed.but i don't know how to do so.i have searched about key bindings but got nothing helpful for me at that initial stage.here is my action that i want to perform at key pressed..
private void addItemActionPerformed(java.awt.event.ActionEvent evt) {
int quantity,price;
Product p=new Product();
String[] result=new String[8];
String data[]=new String[6];
int i=0;
result=p.getInfo(this.addItemField.getText());
for(String s:result){
data[i]=s;
i+=1;
}
data[0]="1";
quantity=Integer.parseInt(data[0]);
price=Integer.parseInt(data[5]);
int tPrice=price*quantity;
data[5]=Integer.toString(tPrice);
System.out.println(quantity+" "+price);
table.addRow(data);
this.addItemField.grabFocus();
}
and here is my default constructor
public SellWindow() {
initComponents();
String title[]={"Qty","Code","Name","Unit Value","ml/kg","Line Total","Action"};
entry.getColumnModel().getColumn(0).setPreferredWidth(20);
table.setColumnIdentifiers(title);
this.entry.setModel(table);
}
i mean the action is executed when i clicked the button(Add item).i want it to be executed also when i pressed the ENTER in keyboard
You can make a button on the dialog the default button. It will be invoked when the Enter key is pressed. See Enter Key and Button for a solution.
If the data to be added is being entered in a JTextField, an actionEvent should be fired when you press enter.
inputField.addActionListener(listener);
Where listener is the container for your actionPerformed method.
But otherwise go with Nizil's suggestion and use KetListener.

Pressed button as a hotkey

I'm trying to make something like hotkey textbox. User presses F11 / Caps lock / any key and it appears in the box.
I did it this way:
#Override
public void keyPressed(KeyEvent e) {
textField_1.setText(String.valueOf(e.getKeyChar()));
}
but it doesn't work for the Fs, caps lock etc. (what is obvious, because those aren't chars).
How can I deal with this problem?
You can use:
event.getKeyCode();
But in general you should probably use Key Bindings.
As Agusti-N states in his answer:
The interface KeyListener contain three methods:
void keyTyped(KeyEvent)
void keyPressed(KeyEvent)
void keyReleased(KeyEvent)
If you use keyPressed and you are using event.getKeyChar() to check for the character entered, this will not work. You should use getKeyChar() for keyTyped and getKeyCode() for keyPressed and keyReleased. Otherwise you'll get null.
As stated in the javadoc.
You probably want to use e.getKeyText() instead of e.getKeyChar() that will return F1 if the F1 key is presed. Here is the API description:
getKeyText
public static String getKeyText(int keyCode)
Returns a String describing the keyCode, such as "HOME", "F1" or "A".
These strings can be localized by changing the awt.properties file.
Returns: a string containing a text description for a physical key, identified by its keyCode
-- http://docs.oracle.com/javase/6/docs/api/java/awt/event/KeyEvent.html#getKeyText(int)
Alternatively:
You could also use e.getKeyCode that will give you the key codes for the various key events identified their corresponding constant values. For instance, e.getKeyCode will return 112 as the value for a key press for F1, which can be accessed by the constant VK_F1. Following is the API Description:
getKeyCode
public int getKeyCode()
Returns the integer keyCode associated with
the key in this event.
Returns: the integer code for an actual key on
the keyboard. (For KEY_TYPED events, the keyCode is VK_UNDEFINED.)
-- http://docs.oracle.com/javase/6/docs/api/java/awt/event/KeyEvent.html#getKeyCode()
And here are the listings for the Key Constants: http://docs.oracle.com/javase/6/docs/api/constant-values.html#java.awt.event.KeyEvent.CHAR_UNDEFINED

Mimicking jQuery event.which in GWT

The GwtQuery documentation provides the following example as a starting point for fiddling with events:
$("h1").bind(Event.ONMOUSEOVER | Event.ONMOUSEOUT, new Function() {
public boolean f(Event e) {
$(e).toggleClass("highlight");
return true;
}
});
However, unlike the jQuery parallel, there is no this keyword to refer to the element inside the handler, that's why it is passed as Event e, to be wrapped within $(). But then, we don't have access to the actual event. How do we calculate in GWT what we can in jQuery with event.which, or event.target?
Specifically, I am looking for two events. One is a mousedown, after which I need to check whether it was the left button (jQuery equivalent being e.which == 1), and a keyup event, after which I need to check for specific keys (e.keyCode == 13, etc).
The Event object passed to the function is the GWT object com.google.gwt.user.client.Event
So if you want to know if the left button was pressed :
if (e.getButton() == NativeEvent.BUTTON_LEFT){
...
}
if you want to know which key was pressed:
e.getCharCode()

Categories