在Qt的keyPressEvent()和keyReleaseEvent()中,我试图获取key +修饰符的小键盘输入。
使用void MyWidget::keyPressEvent(QKeyEvent *evt)
,evt->key()
提供键码(Qt::Key),evt->modifiers()
提供键盘修饰符(QFlags)。
我发现shift key overrides NumLock。
下表显示了有关按键事件的所有可用Qt值的读数。
要重现的按键:关闭NumLock,按下并释放num_5,然后按下并释放shift,然后按shift->按num_5->释放num_5->释放shift,然后将NumLock切换为开并重复相同的按键操作。
table headers:
natSC = evt->nativeScanCode()
natMods = evt->nativeModifiers()
kbdMods = QGuiApplication::keyboardModifiers()
queryKbdMods = QGuiApplication::queryKeyboardModifiers()
NumLock | Action | Event | evt->key() | evt->modifiers() | natSC | natMods | kbdMods | queryKbdMods
--------+---------------+------------+-------------+------------------+-------+----------+--------------+-------------
off | Num_5 down | keyPress | Key_Clear | Keypad | 76 | 0 | Keypad | 0
off | Num_5 up | keyRelease | Key_Clear | Keypad | 76 | 0 | Keypad | 0
off | Shift down | keyPress | Key_Shift | Shift | 42 | 1 | 0 | Shift
off | Shift up | keyRelease | Key_Shift | 0 | 42 | 0 | Shift | 0
off | Shift down | keyPress | Key_Shift | Shift | 42 | 1 | 0 | Shift
off | Num_5 down | keyPress | Key_Clear | Shift+Keypad | 76 | 1 | Shift+Keypad | Shift
off | Num_5 up | keyRelease | Key_Clear | Shift+Keypad | 76 | 1 | Shift+Keypad | Shift
off | Shift up | keyRelease | Key_Shift | 0 | 42 | 0 | Shift | 0
--------+---------------+------------+-------------+------------------+-------+----------+--------------+-------------
on | NumLock dwn | keyPress | Key_NumLock | Keypad | 325 | 16777728 | Keypad | 0
on | NumLock up | keyRelease | Key_NumLock | Keypad | 325 | 16777728 | Keypad | 0
--------+---------------+------------+-------------+------------------+-------+----------+--------------+-------------
on | Num_5 down | keyPress | Key_5 | Keypad | 76 | 512 | Keypad | 0
on | Num_5 up | keyRelease | Key_5 | Keypad | 76 | 512 | Keypad | 0
on | Shift down | keyPress | Key_Shift | Shift | 42 | 513 | 0 | Shift
on | Shift up | keyRelease | Key_Shift | 0 | 42 | 512 | Shift | 0
on | Shift down | keyPress | Key_Shift | Shift | 42 | 513 | 0 | Shift
on | Num_5 down | keyRelease | Key_Shift | 0 | 42 | 512 | Shift | 0
on | ...Num_5 down | keyPress | Key_Clear | Keypad | 76 | 512 | Keypad | 0
on | Num_5 up | keyRelease | Key_Clear | Keypad | 76 | 512 | Keypad | Shift
on | ...Num_5 up | keyPress | Key_Shift | Shift | 42 | 513 | 0 | Shift
on | Shift up | keyRelease | Key_Shift | 0 | 42 | 512 | Shift | 0
您可以看到该移位似乎是在numpad键事件之前释放的。
问题在于,此“虚拟”换档事件看起来与常规换档完全相同。
我理想的解决方案是在keyPressEvent()中获得真实的类次状态。
作为一种解决方法,我很乐意测试是否在keyPressEvent()中启用了NumLock-然后,如果用户按下shift键并要求禁用NumLock,我可以给出警告。
我正在使用Win7,但是解决方案应该是可移植的,例如使用Qt。有任何想法吗?
我也会满意地回答“这不可能,因为...”。
最佳答案
获取NumLock状态
此类任务由Windows API在Windows中执行,而在Unix系统中由X11负责。如果您想同时运行代码,则可以使用条件编译。
#ifdef _WIN32
// Code for windows
#else
#ifdef __linux__ // Systems based on the Linux kernel define this macro.
// Code for linux.
#else
对于Windows,我建议: GetKeyState 函数摘自Visual Studio文档:
GetKeyState
返回值类型简短
对于Linux:使用XLib。
这是一个多平台示例代码:
#ifdef _WIN32
#include <Windows.h>
#endif
#ifdef _UNIX
#include <X11/Xlib.h>
#endif
#include <iostream>
bool is_numlock_activated()
{
#ifdef _WIN32
short status = GetKeyState(VK_NUMLOCK);
return status == 1;
#endif
#ifdef _UNIX
Display *dpy = XOpenDisplay(":0");
XKeyboardState x;
XGetKeyboardControl(dpy, &x);
XCloseDisplay(dpy);
return x.led_mask & 2;
#endif
}
int main()
{
if (is_numlock_activated())
std::cout << "NumLock is activated.";
else
std::cout << "NumLock is deactivated.";
std::cout << std::endl;
return 0;
}
请注意,如果您没有运行X Server,则此代码在Linux上将不起作用。这是无关紧要的,因为您正在开发桌面应用程序,因此,如果可以运行您的应用程序,则可以运行此代码。获取轮类状态
为此(对于Linux),除了 Xlib.h 之外,您还需要包括XKB扩展名。
#ifdef _UNIX
#include <X11/XKBlib.h>
#endif
bool is_shift_pressed()
{
bool result;
#ifdef _WIN32
short status = GetKeyState(VK_SHIFT);
return status == 0xF0; // Here we are checking the High order bit.
// See GetKeyState documentation above.
#endif
#ifdef _UNIX
Display *dpy = XOpenDisplay(":0");
XkbStateRec sate;
XkbGetSate(dpy, XkbUseCoreKbd, &sate);
XCloseDisplay(dpy);
return state.mods & 1; // 1 is the mask for modifier SHIFT.
#endif
}
我是从 superuser.com 的这个answer中获得的这一代码段(Linux的代码段)。