从 Qt 中的 QKeyEvent 获取键的“名称”

Posted

技术标签:

【中文标题】从 Qt 中的 QKeyEvent 获取键的“名称”【英文标题】:Get the "name" of a key from QKeyEvent in Qt 【发布时间】:2014-02-13 19:49:50 【问题描述】:

是否有一种简单的方法来获取键的名称(例如从键事件中获取“向上箭头”而不是仅获取键代码“16777235”)?我必须自己制作一个键名列表吗?

【问题讨论】:

为什么不直接用枚举来表示键值呢? 【参考方案1】:

在代码中使用人类可读的名称

您可以使用Qt::Key 枚举,或使用QKeyEvent::text() 以字符串形式获取密钥。

来自QKeyEvent documentation:

int QKeyEvent::key () const

返回被按下或释放的键的代码。

有关键盘代码列表,请参见 Qt::Key。这些代码独立于底层的窗口系统。请注意,此函数不区分大写字母和非大写字母,为此请使用 text() 函数(返回密钥生成的 Unicode 文本)。

...

Qt::Key 是一个枚举,它将数字键 ID(如 QKeyEvent::key() 的返回值)映射到 程序员可读的名称,如 Qt::Key_Up

如果只关心字母数字键,也可以使用QKeyEvent::text()获取值:

QString QKeyEvent::text () const

返回此键生成的 Unicode 文本。在按下或释放修饰键(例如 Shift、Control、Alt 和 Meta)的情况下,返回的文本可以是空字符串。在这种情况下,key() 将包含一个有效值。

参见 Qt::WA_KeyCompression。

向用户显示人类可读的名称

使用QKeySequence::toString() 或建立自己的“好”名字表。

让人类可读的键名向用户显示的最简单方法是使用QKeySequence::toString()。

这是一个例子:

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

如果您不喜欢 QKeySequence 使用的名称(例如,您想使用“向上箭头”而不是“向上”),则需要创建数据表以将枚举值重新映射到您的首选名称。

【讨论】:

谢谢,QKeySequence::toString 正是我所需要的。【参考方案2】:

另一种方法利用 Qt 元对象系统和对 Qt 命名空间中大多数枚举的内省。这适用于 Qt 4 和 Qt 5。

// https://github.com/KubaO/***n/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");

然后您可以在keyPressEvent 中使用它,如下所示:

void MyWidget::keyPressEvent(QKeyEvent * ev) 
  qDebug() << keyName(ev->key());

【讨论】:

有一点需要注意,KeyHelper 类没有考虑 shift/ctrl/alt 等。 bool isShift = index & Qt::SHIFT; bool isCtrl = index & Qt::CTRL; bool isAlt = index & Qt::ALT; bool isMeta = index & Qt::META;索引 &= ~Qt::MODIFIER_MASK;会解决的

以上是关于从 Qt 中的 QKeyEvent 获取键的“名称”的主要内容,如果未能解决你的问题,请参考以下文章

qt 中怎么实现对键盘按键按下的响应

Qt - 实现 QKeyEvent

如何接受/忽略 QKeyEvent

确定 QKeyEvent 的来源

使用Mongolite获取集合中所有键的名称

QKeyEvent.nativeModifiers() 是啥?