Get the "name" of a key from QKeyEvent in Qt
Asked Answered
T

2

14

Is there an easy way of getting the name of a key (so something like "uparrow" from a key event instead of just getting the key code "16777235")? Do I have to make a list of key names myself?

Tum answered 13/2, 2014 at 19:49 Comment(1)
Why not just make enums to represent the key values?Polygamist
S
21

Using human-readable names in your code

You can use the Qt::Key enum, or get the key as a string with QKeyEvent::text().

From QKeyEvent documentation:

int QKeyEvent::key () const

Returns the code of the key that was pressed or released.

See Qt::Key for the list of keyboard codes. These codes are independent of the underlying window system. Note that this function does not distinguish between capital and non-capital letters, use the text() function (returning the Unicode text the key generated) for this purpose.

...

Qt::Key is an enum that maps numeric key IDs (like the return value of QKeyEvent::key()) to programmer-readable names like Qt::Key_Up.

If you only care about alphanumeric keys, you can also use QKeyEvent::text() to get the value:

QString QKeyEvent::text () const

Returns the Unicode text that this key generated. The text returned can be an empty string in cases where modifier keys, such as Shift, Control, Alt, and Meta, are being pressed or released. In such cases key() will contain a valid value.

See also Qt::WA_KeyCompression.

Displaying human-readable names to the user

Use QKeySequence::toString() or build your own table of "nice" names.

The easiest way to get human-readable key names to show to the user is to use QKeySequence::toString().

Here's an example:

Qt::Key key = Qt::Key_Up;
qDebug() << QKeySequence(key).toString(); // prints "Up"

If you don't like the names that QKeySequence uses (e.g. you want to use "Up Arrow" instead of "Up"), you'll need to make your data table to remap the enum values to your preferred names.

Shiksa answered 13/2, 2014 at 20:3 Comment(1)
Thanks, QKeySequence::toString was exactly what I needed.Tum
F
7

Another approach leverages the Qt metaobject system and the introspection into most enumerations in the Qt namespace. This works in both Qt 4 and Qt 5.

// https://github.com/KubaO/stackoverflown/tree/master/questions/keyname-21764138
#include <QMetaEnum>

namespace SO {
enum KeyNameOption { KeyNameNone = 0, AppendArrow = 1 };
Q_DECLARE_FLAGS(KeyNameOptions, KeyNameOption)
}
QString keyName(int index, SO::KeyNameOptions opt = {}) {
   constexpr static auto const getEnum = [](const char *name) {
      int enumIndex = qt_getQtMetaObject()->indexOfEnumerator(name);
      return qt_getQtMetaObject()->enumerator(enumIndex);
   };
   static const auto keyEnum = getEnum("Key");
   static const auto modifierEnum = getEnum("KeyboardModifiers");

   auto name = modifierEnum.valueToKeys(index & Qt::KeyboardModifierMask);
   index &= ~Qt::KeyboardModifierMask;

   if (name == "NoModifier")
      name.clear();
   else {
      name.replace('|', '+');
      name.replace("Modifier", "");
      name.append('+');
   }

   auto keyName = keyEnum.valueToKey(index);
   if (keyName)
      name.append(keyName + 4);
   if ((opt & SO::AppendArrow) && index >= Qt::Key_Left && index <= Qt::Key_Down)
      name.append(" Arrow");
   return QLatin1String(name);
}

int main() {
   Q_ASSERT(keyName(Qt::Key_Tab) == "Tab");
   Q_ASSERT(keyName(Qt::ShiftModifier | Qt::Key_Up, SO::AppendArrow) == "Shift+Up Arrow");
   Q_ASSERT(keyName(Qt::AltModifier | Qt::Key_Down) == "Alt+Down");
}

You'd then use it in, say, keyPressEvent, as follows:

void MyWidget::keyPressEvent(QKeyEvent * ev) {
  qDebug() << keyName(ev->key());
}
Francefrancene answered 13/2, 2014 at 22:40 Comment(1)
One thing to note, class KeyHelper does NOT take into account shift/ctrl/alt etc. bool isShift = index & Qt::SHIFT; bool isCtrl = index & Qt::CTRL; bool isAlt = index & Qt::ALT; bool isMeta = index & Qt::META; index &= ~Qt::MODIFIER_MASK; Will fix itGrandstand

© 2022 - 2024 — McMap. All rights reserved.