Problem with keylistener - java

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.

Related

Multiple Keylisteners 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.

How to make Java JButton visually depress with touch screen?

I've got a simple Swing GUI with JButtons being run on a Surface tablet with a touchscreen. The buttons have ActionListeners. When these buttons are clicked from a mouse they visually depress correctly. However when they are tapped on the touchscreen they remain visually the same but still fire off an actionPerformed(). If they are double tapped then they visually depress correctly but fire off 2 actionPerformed()s.
Is there a way to get this button animation change to take place when the button is pressed, rather than clicked? I've tested it and I could use a MouseListener and put all my logic in mouseClicked() but it's not very elegant to ask touchscreen users to double tap a button.
The problem you have is that whereas a mouse click is a compound event, a touch on the screen is not. So there's no way that it can go down at the first event and up again at the second.
But what you can do, when you receive a touch event, is change the visual state of the button so it looks depressed (using setPressed(true)), then set a timer for 100ms or so, and set the state back to normal when the timer expires (using setPressed(false)).
Careful with the timer expiration: you need the setPressed(false) to happen on the UI thread. So you'll need to use SwingUtilities.invokeLater() as a wrapper round the second call to setPressed. Or, alternatively, use a javax.swing.Timer as the means of queueing the second call; it takes a delay and an Action, and the Action gets performed on the UI thread.
I use mouse listener but I implement my logic in the moussePressed method and it this works perfectly in IBM touch screens
class BtnNumbMl implements MouseListener {
public void mousePressed(MouseEvent e) {
**//your logic goes here**
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
have a good day

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 :)

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;
}
}
});

Categories