Short Version:
How do I determine when a KeyBind key has been released in similar functionality to a KeyListener keyReleased() event?
Long Version:
I am experimenting a bit with making a very simple game, and I was using several KeyListeners to track my keyboard input. However, as I added more complicated features, I began to encounter issues with the keyboard input not receiving proper focus and thus no keyboard input was being received.
Then I read about KeyBinds. While the KeyBinds functionality fixed my focus issue, for my game I was wanting to change a value based off whether a key was pressed or not. I can get the value to change through pressing the key, but I don't know how to detect when the key is released. The KeyListener had a separate KeyPressed and KeyReleased method, but that won't work correctly due to component focusing issues.
Relevant Code:
I don't have a lot of code to share because the input was simply needed to call one of two methods which are set up in another class (and I was testing KeyBinds). But here is the relevant KeyBind code anyway:
Action myAction = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println("testing action output");
}
};
actionMap = getActionMap();
inputMap = getInputMap(condition);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "leftArrow");
actionMap.put("leftArrow", myAction);
And here's the code I was using with KeyListener (again, very little since I just call a method)
addKeyListener(new KeyListener()
{
#Override
public void keyPressed(KeyEvent e)
{
racquetClass.keyPressed(e);
}
#Override
public void keyReleased(KeyEvent e)
{
racquetClass.keyReleased(e);
}
#Override
public void keyTyped(KeyEvent e)
{
}
});
Thanks in advance to any and all help that can be provided.
but I don't know how to detect when the key is released.
You need to create a separate Key Binding:
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "leftArrowReleased");
actionMap.put("leftArrowReleased", myReleasedAction);
Related
I am trying to have a window pop up when key 1 is pressed and a separate window when key 2 is pressed.
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_1)
{
TicTacToeDriver tic = new TicTacToeDriver();
PointCounter();
}
else if(e.getKeyCode() == KeyEvent.VK_2)
{
HangmanDriver hang = new HangmanDriver();
PointCounter();
}
}
public void keyReleased(KeyEvent e)
{
//do nothing
}
public void keyTyped(KeyEvent e)
{
//do nothing
}
The tic tac toe and hangman games were created by two separate people and the programmers created their own driver.
Solution:
I am assuming that the programmers are familiar with java oriented programming...
Thus, You would just create a new object of one of the games.
Hangman h = new Hangman();
or
Tick h = new Tick();
Tick.start() //depending on their code.
If you are running a Jframe...
you would need to
(insert object name).setVisible(true);
Since you mentioned that they have drivers I assume that they use main methods instead of constructors even though the code you provided creates objects of the classes.
Thus, when the button is clicked or key is pressed.. Just call the main method of the driver class.
hangman.main(null); //this is a terrible way to do it btw.
I also recommend using KeyBindings API instead of keylistener as keybindings does not require focus... which could also be problem.
Another problem would be..
this.addKeyListener(this);
You have to add the keylistener to the component.
But, this is where problems arise as you are using keylistener.. Your JComponent that you added the KeyListener to might not have focus. Thus, the action wont fire till the component has focus and an action is triggered.
Right now, when I add a KeyListener to a JTextField, I get an event, then the text updates. But what I need is for the KeyListener to respond after the text is updated. How would I go about doing that? Right now, I am setting a 10-millisecond delay to the response of the KeyListener in another thread, which is sufficient for the text to update and the user to not notice.
Don't use a KeyListener. Swing has newer and better API's than AWT.
Instead you should be adding a DocumentListener to the Document of the JTextfield
A DocumentEvent is generated whenever the Document is updated.
Read the section from the Swing tutorial on How to Write a DocumentListener for more information and examples.
So.... ummmm i know it's kind'a late X)
I kind'a gone around that by using the keyReleased method I noticed that the text gets updated before the key event it should give you something like this
JTextField jtf = new JTextField();
jtf.addKeyaddKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// not here
}
#Override
public void keyReleased(KeyEvent e) {
// not here
}
#Override
public void keyPressed(KeyEvent e) {
//do the stuff here
}
});
note that I am not sure why it works but I would think that it has something to do with the typing speed or something, also I am not an expert but i wanted to help (that problem drove me crazy for a couple days) if i am saying any stupid stuff pleas let me know !
I have a KeyHandler class that implements KeyListener. All keys are working except for the left and right arrow keys which register as pressed but never as released (up and down arrows work, as all other keys do). The key listener is added to a Canvas on a JFrame.
public class KeyHandler implements KeyListener {
public void keyPressed(KeyEvent e) {
System.out.println("Pressed");
}
public void keyReleased(KeyEvent e) {
System.out.println("Released");
}
public void keyTyped(KeyEvent e) {}
}
Is there a reason for this behavior?
Snippet from java api - Keyevent:
Not all keyboards or systems are capable of generating all virtual key codes. No attempt is made in Java to generate these keys artificially.
So from Java- side it is still defined behaviour. However from my logic feeling I also cannot give you any difference between up/down and left/right arrow keys.
Just if we follow the API definition. It seems to be system dependent.
I want to be able to receive input from the keyboard by the user but I've added everything I thought would allow my program to do this and still it does not work. What am I doing wrong?
class KeyInput implements KeyListener {
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed");
}
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased");
}
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped");
}
}
public GameView() {
this.addKeyListener(new KeyInput());
}
The constructor works fine and KeyInput is an inner class of the GameView object.
When running the game, if I press a key nothing gets printed to the system output.
Am I missing something? Thanks!
KeyListener is fickle mistress, it wants a lot of attention all the time. Basically, it will only raise key events if the component it is registered to has focus AND is focusable.
Generally, you want to avoid using it and use key bindings API instead, How to Use Key Bindings, but this will depend on whether you MUST use pure AWT APIs or not....
my big problem is that i am codding a game.i have 2 player in a jframe that they can play cuncurrent. first player play with arrow keys and second with w/a/s/d keys..my instrutor said me that to achieve cuncurrent play i should instantiate two thread that every thread manage its own special player..noe i am confuse that how i can have two thread for tow players that only diffrence between them is the key that they listen...
another question that maybe can help me is can i have a listener that listen only some special keys??for exampe i new a listener that only listen w/s/a/d buttuns??(i am familiar with keyevent.getkeycode but it is not my mean because i want a listener that never listen another keys this is listen all keys and in decision choose codder favorite key)
i will be infinitively greatfull if you help me.
You can define your own keys processors like this (mainFrame is JFrame instance)
ActionMap actions = ((JComponent)mainFrame.getContentPane()).getActionMap();
InputMap inputs = ((JComponent)mainFrame.getContentPane()).getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
Action a=new AbstractAction() {
public void actionPerformed(ActionEvent e) {
//call your action code here
}
};
actions.put("myAction", a);
inputs.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK), "myAction");
before that don't forget to set Focus to the JPanel before listening KeyListener check KeyBindings for extended funcionalities, here is very usefull infos about Listeners in Swing
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myPanel.grabFocus();
myPanel.requestFocus();//or requestFocusinWindow()
}
});
A key listener will listen to all keys. You just have to react to the ones you need. Since you can have any number of key listeners, there is no issue in having a key listener per player.
The keyListener listens to all keys pressed.
But inside the code you can check which key is pressed, if ignore it if it is not one of the keys that you want to react to. In fact, you could use the same class for both listeners and just pass the key that each of them has to react to as parameters.
Having said that, you should not need two threads for it. I understand two threads to avoid the GUI freezing (a thread for managing the GUI, another for doing the calculations of positions). Of course, being it homework, it can be asked this way just so get to learn the basic concepts of threading.
Ok so heres how i would do it, i would have 2 classes, one called game and the other player, game extends your JFrame and player implements your keyListener, In game you could have 2 instances of Player, one for the instance that uses the D-keys and the other would use asdw or whatever, heres an example:
public void keyPressed(KeyEvent e)
{
switch(playerNumber)
{
case PLAYER_1:
if(e.getKeyCode==VK_UP)
{
//do some code for an "up event"
}
if(e.getKeyCode==VK_DOWN)
{
//do some code for a "down event"
}
if(e.getKeyCode==VK_LEFT)
{
//do some code for a "left event"
}
if(e.getKeyCode==VK_RIGHT)
{
//do some code for a "right event"
}
break;
case PLAYER_2:
if(e.getKeyCode==VK_W)
{
//do some code for an "up event"
}
if(e.getKeyCode==VK_S)
{
//do some code for a "down event"
}
if(e.getKeyCode==VK_A)
{
//do some code for a "left event"
}
if(e.getKeyCode==VK_D)
{
//do some code for a "right event"
}
break;
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public static final int PLAYER_1 = 0;
public static final int PLAYER_2 = 1;
all you would have to do is tell the player instance if its player1 or player2, which would be easy, if you need any more examples or anything let me know, ive made plenty of hotseat games (games where more than 1 person are playing on 1 computer).