Having tried KeyEvents it was recommended that I switch to Key Bindings to activate certain events by the pushing of the arrow keys while one is in a TextArea
area.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke("VK_UP"),
"doEnterAction");
area.getActionMap().put("doEnterAction", new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e){
System.out.println("Event Handled");
oneRay[pick][0] = ("");
if(i>=4){
i=0;
area.setText("");
}
caller();
}
});
area.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke("VK_DOWN"),
"doEnterAction");
area.getActionMap().put("doEnterAction", new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e){
System.out.println("Event 2 Handled");
area.append("\n"+oneRay[pick][1]);
buton1.setEnabled(true);
buton2.setEnabled(true);
}
});
area.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke("VK_RIGHT"),
"doEnterAction");
area.getActionMap().put("doEnterAction", new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e){
if(i>=4){
i=0;
area.setText("");
}
caller();
}
This code covers three different Key Bindings, but none work, whether I press up down left right the cursor just moves in that direction in the TextArea.
What have I done wrong this time. Please help me!
whether I press up down left right the cursor just moves in that direction in the TextArea.
You are building the KeyStroke incorrectly. You should not be including the "VK_" in the Keystroke. So basically nothing is being added to the InputMap.
Also your code is updating the InputMap and ActionMap with a new identifier. I find is easier to just replace the Action in the ActionMap. See Key Bindings for a list of all the default Actions as well as the basic code for replacing the default Action (this is a different link than you got in your last posting).
Finally, in your other posting you suggested that you want to invoke the Action of a button. Well then your code should be creating an Action that can be used by the button and the Key Bindings. You create an Action the same way you create an ActionListener except you extend AbstractAction instead of implementing ActionListener.
Related
I have a JPanel that I need to check for the control being pressed down so that the user can select multiple things on screen, i had the issues of using a key listener so after research i found that i was supposed to use key bindings, and i finally got it to work for pressing control, but i cant get it to work for releasing control
'''
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,
InputEvent.CTRL_DOWN_MASK), "press");
getActionMap().put("press", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
controlPressed = true;
}
});
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.CTRL_DOWN_MASK
,InputEvent.CTRL_DOWN_MASK,true), "release");
getActionMap().put("release", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("release");
controlPressed = false;
}
});
'''
so pressing ctrl works but releasing does not, any ideas?
Update, I found what I think is the best solution for my problem, the mouse event stores weather or not control is pressed down so there was no need to do any magic with keysListeners or binding keys. here is the line of code if anyone needs it
'''
public void mousePressed(MouseEvent e){
e.isControlDown();
}
'''
currently im trying to code a grid based game.
ive already managed to implement a key listener for general navigation.
but when pressing a certain key, a Jpopup Menu opens.
now i want to implement navigation for the menu aswell with a key listener. Pressing B is supposed to close the menu again.
KeyListener UnitActionMenuKeyListener = new KeyListener() {
#Override
public void keyPressed(KeyEvent evt)
{
if (evt.getKeyCode()==KeyEvent.VK_B)
menu.setVisible(false)
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
JPopupMenu menu = new JPopupMenu("UnitActionMenu");
JMenuItem bewegenItem = menu.add("test");
Using menu.show and menu.addKeyListener after this.
But no matter what i try, either my general navigation wont work anymore, or the general navigation will work, but my menu wont react to pressing B
so, how do i implement multiple key listeners for multiple elements?
i just want my main window to listen (and react) to some key differently than my menu
(sorry for bad writing, my english isnt that good and im frustrated by failing a simple task for more than 4 hours)
Swing key bindings are generally better than key listeners. Key listeners have issues related to the focus system. That's what the problem you're having sounds like. When the popup is active, it steals the focus. Only the focused component will send out key events.
There's a tutorial for key bindings here: https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
The API is a little more complicated but they're more robust and you can specify the focus behavior directly.
Here's a quick guide for converting key listeners to key bindings.
For a key listener, you have some code that's like this:
myComponent.addKeyListener(new KeyListener() {
...
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_Z)
performZAction();
}
});
Writing a key binding would be like this:
KeyStroke keystroke =
KeyStroke.getKeyStroke("typed Z");
myComponent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(keystroke, "zAction");
myComponent.getActionMap()
.put("zAction", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
performZAction();
}
});
In other words, there are three steps:
Creating a javax.swing.KeyStroke object with KeyStroke.getKeyStroke.
Using the input map, bind the keystroke to a name for your action.
Using the action map, bind the name for your action to a javax.swing.Action.
The Action is your listener. You can extend javax.swing.AbstractAction and it's just like writing an ActionListener.
Guys weird problem im facing
Basically i have 2 textAreas... (diplaybox and textbox)
while typing in textbox, the moment "Enter" is pressed i want all the text entered in textbox to go to displaybox... and textbox should be empty...
it all works fine, except...
after the text is transfered the cursor position of the textbox isnt on the topmost left side... it is somehow blinking on one line below that!(possibly because "ENTER" still got excecuted)... please see code
any ideas?
thanks in advance... just need the cursor to go back to the topmost left like how it is when we start typing ... without having to use KeyReleased event... something isnt feeling right... im sure this isnt he way it is actually done.. what say?
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_ENTER)// | (e.getKeyCode() == KeyEvent.VK_B))
{ //Toolkit.getDefaultToolkit().beep();
displaybox.append(textbox.getText() + "\n");
//textbox.setCaretPosition(0);
//textbox.setText("");
System.out.println(textbox.getCaretPosition());
}
}
public void keyTyped(KeyEvent e)
{}
public void keyReleased(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_ENTER)
{textbox.setCaretPosition(0);
textbox.setText("");
System.out.println(textbox.getCaretPosition());
}
}
All Swing components work by using Key Bindings. The default binding for the Enter key is to add a newline string to the text area. If you want to change the functionality of the Enter key then change the default Action. Don't attempt to use a KeyListener.
Check out Key Bindings for a program to list all the default bindings as well as a link to the Swinng tutorial on How to Use Key Bindings. If you run the program you will find that the Enter key invokes an Action identified by the "insert-break" tag in the ActionMap. So to replace the Action you can do something like:
Action enter = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
displayBox.append( textBox.getText() + "\n" );
textBox.setText("");
}
};
textBox.getActionMap().put("insert-break", enter);
The problem with using the KeyListener is that the default Action is still invoked AFTER you process the KeyEvent.
I'm using this code to bind keyboard keys to custom actions without using the KeyListener:
Action left = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("pressed left key");
}
};
Action right = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("pressed right key");
}
};
Action space = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("pressed space key");
}
};
myJPanel.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), "pressedLeft");
myJPanel.getInputMap().put(KeyStroke.getKeyStroke("A"), "pressedLeft");
myJPanel.getActionMap().put("pressedLeft", left);
myJPanel.getInputMap().put(KeyStroke.getKeyStroke("RIGHT"), "pressedRight");
myJPanel.getInputMap().put(KeyStroke.getKeyStroke("D"), "pressedRight");
myJPanel.getActionMap().put("pressedRight", right);
myJPanel.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressedSpace");
myJPanel.getActionMap().put("pressedSpace", space);
Everything works perfectly, but i noticed that when i press i.e. SPACE while holding A, the left action isn't fired anymore, it would be great if events for both pressed keys are fired.
Is there any way to use key bindings with key combinations?
See Motion Using the KeyBoard for a potential solution.
An event is only generated for the last key pressed so you need to manually keep track of any other keys that have been pressed (and keep manually simulate firing the event). This is true whether you use key bindings or a KeyListener.
hi i'm using swing and in my main frame(JFrame) i want that when ever user press + key one window lets say test should appear.
my key listener works fine if i don't call the show method of the newly added JInternalFrame but when i call the show method of my JInternalFrame the KeyListener stops listening any more.
i've tried a lot to solve it but all in vain so any help regarding this will be appreciated.
thanks.
this is my keyListener
_mainFrameKeyListener = new KeyListener()
{
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
System.out.println("the key pressed Id is : " + arg0.getKeyCode());
if(arg0.getKeyCode() == 107){
test Test = new test();
_mainDesktopPane.add(Test);
Test.show();
}
}
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
};
Sounds like you want a hot key instead of a key listener to avoid focus issues.
// Get the KeyStroke for our hot key
KeyStroke plus = KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, 0, true);
// Get the input map for our component
// In this case we are interested in key strokes in the focussed window
InputMap inputMap = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
// Map the key stroke to our "action key" (see below)
inputMap.put(plus, "my_action");
// Get the action map for our component
ActionMap actionMap = panel.getActionMap();
// Add the required action listener to out action map
actionMap.put("my_action", actionListener);
http://helpdesk.objects.com.au/java/how-to-specify-a-hot-key-for-a-swing-application
You would need to add the key listener to exactly the component that has focus (many components are actually composites).
So use JComponent.registerKeyboardAction with a condition of WHEN_IN_FOCUSED_WINDOW. Alternatively use JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW, true) and JComponent.getActionMap(true) as described in the registerKeyboardAction API docs.
Please check whether a runtime exception is thrown. may be you are in the wrong thread for showing this dialog or another issue could throw this exception.
Also please think about to use a asynch thread for showing your dialog instead of using the listener thread. But this is just a think about.