Вопрос
Я несколько незнаком с тем, как работает Java KeyAdapter
работает, и я получаю неожиданные результаты со следующим кодом, использующим KeyAdapter
.Проблема возникает, когда клавиша нажата, в то время как другая клавиша уже удерживается нажатой, независимо от того, isKeyPressed()
называется.
Примечание:Я знаю, что это большой объем кода, и я приношу свои извинения.Я сделал все, что мог, чтобы изолировать это, и я думаю, что это связано в первую очередь с комментариями в keyHandler
приведенный ниже метод (как keyHandler()
помещает нажатые в данный момент клавиши в keysHeld
).Надеюсь, подробные комментарии окажутся полезными.
Манипулятор с ключами:
ArrayList keysHeld = new ArrayList<KeyEvent>();
private void keyHandler()
{
KeyAdapter keyListnr = new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
int index = 0;
boolean found = false;
while(!found && index<keysHeld.size()) //While not already found, and end of ArrayList not reached
{
System.out.print("errorCheck: keysHeld: "+keysHeld+", "+(Object)keyCode+" "); //PRINT
if(keysHeld.get(index) == (Object)keyCode)
{
System.out.println("found"); //PRINT
found = true; //This key is already recognized as held
}
else
{
System.out.println("not found"); //PRINT
//This key is not recognized as held
}
}
if(!found) //If key must be added to keysHeld
{
keysHeld.add(keyCode); //Add to list of held keys
}
System.out.println(keysHeld.toString()); //PRINT ArrayList of all held keys
} //end of keyPressed
public void keyReleased(KeyEvent e) //similar in concept to keyPressed
{
int keyCode = e.getKeyCode();
int index = 0;
boolean found = false;
while(!found && index < keysHeld.size())
{
if(keysHeld.get(index) == (Object)keyCode)
{
keysHeld.remove(index); //remove key from keysHeld
found = true;
}
else
{
index++;
}
}
System.out.println(keysHeld.toString()); //PRINT ArrayList of all held keys
} //end of keyReleased
};
addKeyListener( keyListnr );
}
исКейХелд:
public boolean isKeyHeld(int e)
{
int keyCode = e;
Object key = (Object)keyCode;
if(!keysHeld.isEmpty())
{
int index = 0;
while(index<keysHeld.size())
{
if(keysHeld.get(index) == key)
{
return true;
}
index++;
}
}
return false;
}
Консольный вывод:(удерживая левую стрелку [37], а затем нажав правую стрелку[39])
[37]
errorCheck: keysHeld: [37], 39 not found
errorCheck: keysHeld: [37], 39 not found
errorCheck: keysHeld: [37], 39 not found
errorCheck: keysHeld: [37], 39 not found
...
Решение
Пара моментов:
- Вы не заполняете свой
keysHeld
массив с экземплярамиKeyEvent
, но с автоматической упаковкойInteger
объекты , производные отint
Коды ключей. - Вам нужно увеличить свой
index
переменная, если вы хотите выйти изwhile
петля вkeyPressed
- Вы не должны использовать
==
чтобы сравнить эти дваObjects
в вашемwhile
петля
Вы можете протестировать что-то вроде следующего:
if(keysHeld.get(index++).equals(new Integer(keyCode))
Другие советы
При работе с несколькими ключами лучше всего использовать keyReleased(KeyEvent)
способ:это упрощает обработку нескольких комбинаций клавиш во время отпускания клавиши.
Что я заметил, так это то, что когда внутри keyPressed()
, У меня получилось бы запечатлеть только одного ключевого персонажа.На keyReleased
, я смог запечатлеть несколько символов (таких как CTRL-V).