Hello,
I'm working on a cross platform application in which user must be able to check whether a particular key is pressed or not.
So, I create a map of keys like this:
std::unordered_set<int> pressedKeys;
std::unordered_set<int> pressedKeys;
To copy to clipboard, switch view to plain text mode
... and store each key when is pressed
e->accept();
mymutex->lock();
qDebug() << "+key:" << e->key() << "=" << e->text() <<", nativeVirtualKey:" << e->nativeVirtualKey() <<", isAutoRepeat:" << e->isAutoRepeat() <<", modifiers" << e->modifiers();;
if(!e->isAutoRepeat()){
// Note that if the event is a multiple-key compressed event that is partly due to auto-repeat,
// isAutoRepeat() function could return either true or false indeterminately.
if( e->modifiers() & Qt::ShiftModifier )
{
pressedKeys.insert(Qt::Key_Shift);
}else{
pressedKeys.erase(Qt::Key_Shift);
}
if( e->modifiers() & Qt::ControlModifier )
{
pressedKeys.insert(Qt::Key_Control);
}else{
pressedKeys.erase(Qt::Key_Control);
}
if( e->modifiers() & Qt::AltModifier )
{
pressedKeys.insert(Qt::Key_Alt);
}else{
pressedKeys.erase(Qt::Key_Alt);
}
if( e->modifiers() & Qt::MetaModifier )
{
pressedKeys.insert(Qt::Key_Meta);
}else{
pressedKeys.erase(Qt::Key_Meta);
}
pressedKeys.insert(e->key());
}
mymutex->unlock();
}
void MyAapp::keyPressEvent(QKeyEvent *e) {
e->accept();
mymutex->lock();
qDebug() << "+key:" << e->key() << "=" << e->text() <<", nativeVirtualKey:" << e->nativeVirtualKey() <<", isAutoRepeat:" << e->isAutoRepeat() <<", modifiers" << e->modifiers();;
if(!e->isAutoRepeat()){
// Note that if the event is a multiple-key compressed event that is partly due to auto-repeat,
// isAutoRepeat() function could return either true or false indeterminately.
if( e->modifiers() & Qt::ShiftModifier )
{
pressedKeys.insert(Qt::Key_Shift);
}else{
pressedKeys.erase(Qt::Key_Shift);
}
if( e->modifiers() & Qt::ControlModifier )
{
pressedKeys.insert(Qt::Key_Control);
}else{
pressedKeys.erase(Qt::Key_Control);
}
if( e->modifiers() & Qt::AltModifier )
{
pressedKeys.insert(Qt::Key_Alt);
}else{
pressedKeys.erase(Qt::Key_Alt);
}
if( e->modifiers() & Qt::MetaModifier )
{
pressedKeys.insert(Qt::Key_Meta);
}else{
pressedKeys.erase(Qt::Key_Meta);
}
pressedKeys.insert(e->key());
}
mymutex->unlock();
}
To copy to clipboard, switch view to plain text mode
... and delete a key when key is released:
e->accept();
mymutex->lock();
qDebug() << "-key:" << e->key() << "=" << e->text() <<", nativeVirtualKey:" << e->nativeVirtualKey() <<", isAutoRepeat:" << e->isAutoRepeat() <<", modifiers" << e->modifiers();;
if(!e->isAutoRepeat()){
pressedKeys.erase(e->key());
if( e->modifiers() & Qt::ShiftModifier )
{
pressedKeys.insert(Qt::Key_Shift);
}else{
pressedKeys.erase(Qt::Key_Shift);
}
if( e->modifiers() & Qt::ControlModifier )
{
pressedKeys.insert(Qt::Key_Control);
}else{
pressedKeys.erase(Qt::Key_Control);
}
if( e->modifiers() & Qt::AltModifier )
{
pressedKeys.insert(Qt::Key_Alt);
}else{
pressedKeys.erase(Qt::Key_Alt);
}
if( e->modifiers() & Qt::MetaModifier )
{
pressedKeys.insert(Qt::Key_Meta);
}else{
pressedKeys.erase(Qt::Key_Meta);
}
}
mymutex->unlock();
}
void MyApp::keyReleaseEvent(QKeyEvent *e) {
e->accept();
mymutex->lock();
qDebug() << "-key:" << e->key() << "=" << e->text() <<", nativeVirtualKey:" << e->nativeVirtualKey() <<", isAutoRepeat:" << e->isAutoRepeat() <<", modifiers" << e->modifiers();;
if(!e->isAutoRepeat()){
pressedKeys.erase(e->key());
if( e->modifiers() & Qt::ShiftModifier )
{
pressedKeys.insert(Qt::Key_Shift);
}else{
pressedKeys.erase(Qt::Key_Shift);
}
if( e->modifiers() & Qt::ControlModifier )
{
pressedKeys.insert(Qt::Key_Control);
}else{
pressedKeys.erase(Qt::Key_Control);
}
if( e->modifiers() & Qt::AltModifier )
{
pressedKeys.insert(Qt::Key_Alt);
}else{
pressedKeys.erase(Qt::Key_Alt);
}
if( e->modifiers() & Qt::MetaModifier )
{
pressedKeys.insert(Qt::Key_Meta);
}else{
pressedKeys.erase(Qt::Key_Meta);
}
}
mymutex->unlock();
}
To copy to clipboard, switch view to plain text mode
Everything is perfect.
To be a cross platform I use Qt Key-enum values for keys (http://doc.qt.io/qt-4.8/qt.html#Key-enum).
The problem appears when I press a sequence like this:
(notation: + is keyPressEvent, - is keyReleaseEvent):
user press SHIFT
+key: 16777248 = "" , nativeVirtualKey: 16 , isAutoRepeat: false , modifiers QFlags<Qt::KeyboardModifiers>(ShiftModifier)
user press "2", but because SHIFT is pressed, then Qt returns Qt::Key_At "@"
+key: 64 = "@" , nativeVirtualKey: 50 , isAutoRepeat: false , modifiers QFlags<Qt::KeyboardModifiers>(ShiftModifier)
-key: 64 = "@" , nativeVirtualKey: 50 , isAutoRepeat: true , modifiers QFlags<Qt::KeyboardModifiers>(ShiftModifier)
... keep pressing SHIFT+2 = "@" but in fact user press "2" key
+key: 64 = "@" , nativeVirtualKey: 50 , isAutoRepeat: true , modifiers QFlags<Qt::KeyboardModifiers>(ShiftModifier)
release SHIFT
-key: 16777248 = "" , nativeVirtualKey: 16 , isAutoRepeat: false , modifiers QFlags<Qt::KeyboardModifiers>(NoModifier)
now the key is "2" but the original key "@"is in map as pressed
+key: 50 = "2" , nativeVirtualKey: 50 , isAutoRepeat: false , modifiers QFlags<Qt::KeyboardModifiers>(NoModifier)
-key: 50 = "2" , nativeVirtualKey: 50 , isAutoRepeat: true , modifiers QFlags<Qt::KeyboardModifiers>(NoModifier)
...
I do not like the fact that Qt return "@" as a key instead of "2".
One of the flaw is in the example above: the "@" key remains in pressedKeys map as pressed even after the key is actually released.
I want to receive the real key, not the combination.
And I need in cross platform way.
Remember that user must be able to check if a specific key is pressed. For this I check if key is in pressedKeys map and return true/false. User use Key-enum values.
Any ideas?
Thanks!
Bookmarks