Multiple Keylisteners Java - java

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.

Related

Key Bindings as Alternative to KeyEvent still nonfunctional

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.

Action when Enter key pressed on ANY TextField

Please do note that this is a different question,
I am writing a java program. I have a form with 10 JTextFields and a 'Submit' button.
How do I make the method for 'Submit' button to be called when the user presses the
enter key on ANY of the 10 text fields?
Should I add KeyListeners to all of the 10 or is there a more efficient way since the text fields and the button are inside a JPanel?
No, Create an common event handler like this ,And attach it to all
Below is a Mock code:
KeyAdapter event= new KeyAdapter() {
public void keyReleased(KeyEvent e) {
//do something
}
public void keyTyped(KeyEvent e) {
// TODO: Do something for the keyTyped event
}
public void keyPressed(KeyEvent e) {
// TODO: Do something for the keyPressed event
}
});
txtField1.addKeyListener(event);
txtField2.addKeyListener(event);
-----
may be a loop also :)

SWT/JFace: How to handle Keyevents for each ViewPart or Form?

I'm building an Eclipse application and I'm trying to make a shortcut for launching an action when pressing F5, and make that the default action when that Tab/ViewPart has the focus.
I have read that this is not possible, or very complex. Is there any simple/straight way of doing it?
I tried with:
Display.getCurrent().addFilter(...)
this.addKeyListener(new KeyAdapter() {...})
...
Making this in the constructor is my best:
this.getShell().addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.keyCode == SWT.F5) {
//doAnything()
}
}
});
And this doesn't work when loaded, but if I switch from this to another View/Tab starts to work. But it works too when others have focus (which I don't want).
Is there anyway of making this work at the start, and only when the focus is in the View?
You should define work in a handler & then should use key bindings as given in this example. You can find a good example here. Hope it solves your need.
You should look at RetargetableActions. I think that's Eclipse way of doing it:
You need to look at extensions org.eclipse.ui.bindings and org.eclipse.ui.contexts.
Define a command and its handler
Define a binding for the command
define context (cxtId)
associate context with command so that command is available only when context is active
Activate context when you open the view or form.
If you get the listener of the events of the component it will listen on the events. And if the event occur for this component it will be notified.
To add listener of the key event on the ViewPart we should create the control which could be able listen on the event.
public class SampleView extends ViewPart {
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "views.SampleView";
private Composite mycomposite;
public void createPartControl(Composite parent) {
mycomposite = new Composite(parent, SWT.FILL);
//then add listener
mycomposite.addKeyListener(keyListener);
}
private KeyListener keyListener = new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
showMessage("key pressed: "+ e.keyCode);
}
};
//the rest of focusing and handle event
private void showMessage(String message) {
MessageDialog.openInformation(
mycomposite.getShell(),
"Sample View",
message);
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
mycomposite.setFocus();
}
}
//the end

Java Swing default focus on frame

I am learning java and Swing right now and trying to develop simple programms for education purposes.
So here is the question.
I have gridlayout and fields on my frame with default text
accNumberField = new JTextField("0", 10);
accNumberField.addFocusListener(new FocusListener() {
int focusCounter = 0;
#Override
public void focusGained(FocusEvent arg0) {
// TODO Auto-generated method stub
if (focusCounter > 0)
accNumberField.setText("");
focusCounter++;
}
What I want is that when user click on field for the first time the default text is disappered. So I add focus listener and used accNumberField.setText(""); in focusGained method.
But the problem is that for default first field in my frame getting focus right in time of frame creation. And default text is disappearing from the begining. I used counter as you can see. But that's not what I wanted.
I want that no field would get focus in time of creation and every field would be able to get focus from the time when user would click on one of them.
Sorry if I spelled something wrong. English is not my native language.
Found a thread having a code example of your desired functionality, Java JTextField with input hint. Precisely, you need to provide your own implementation of JTextField which will be holding the "default-text" in a field, specially created for that.
For your second question, you can set the focus to some button or frame itself.
Is there any reason that you use focusListener()? why not use mouseListener() as follow?
accNumberField.addMouseListener(new MouseAdapter()
{
#Override
public void mouseReleased(MouseEvent e)
{
accNumberField.setText("");
}
});
if you want to clear the text for the first click, you can simply use a boolean:
//outside constructor
private boolean isTextCleared = false;
//in constructor
accNumberField.addMouseListener(new MouseAdapter()
{
#Override
public void mouseReleased(MouseEvent e)
{
if (!isTextCleared)
{
accNumberField.setText("");
isTextCleared = true;
}
}
});

Problem with 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.

Categories