[英]QKeyEvent isAutoRepeat not working?
因此,我有一个应用程序,如果按住某个特定按钮,它将播放音频设备,释放该按钮时,它将停止音频设备。 我使用keyPressEvent
和KeyReleaseEvent
来实现这一点,类似于下面的代码:
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->isAutoRepeat())
{
event->ignore();
}
else
{
if(event->key() == Qt::Key_0)
{
qDebug()<<"key_0 pressed"<<endl;
}
else
{
QWidget::keyPressEvent(event);
}
}
}
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
if(event->isAutoRepeat())
{
event->ignore();
}
else
{
if(event->key() == Qt::Key_0)
{
qDebug()<<"key_0 released"<<endl;
}
else
{
QWidget::keyReleaseEvent(event);
}
}
}
但是显然isAutoRepeat
函数不起作用,因为尽管按下后我没有松开0键,但我仍能看到连续key_0 pressed
并key_0 released
key_0 pressed
打印。 我的代码错误还是其他错误?
谢谢。
编辑
我认为这是因为MainWindow
失去了键盘焦点。 我如何才能真正找出哪个小部件具有焦点? 当按下Qt::Key_0
时,我实际上正在使用一些小部件,但是我想我将所有可能的小部件都设置为Qt::NoFocus
,我想它不起作用。
我正在尝试通过执行以下操作来了解哪个小部件具有焦点:
QWidget * wigdet = QApplication::activeWindow();
qDebug()<<wigdet->accessibleName()<<endl;
但它始终显示一个空字符串。 如何使它打印具有键盘焦点的小部件的名称?
因此,当我也无意中遇到了这个问题(并且grabKeyboard并没有真正帮助)时,我开始研究qtbase。 它通过xcb连接到X11,默认情况下,在重复键的情况下,X11为每个重复键发送一个释放事件,紧随其后的是一个按键事件。 因此,按住某个键将导致XCB_BUTTON_RELEASE / XCB_BUTTON_PRESS-事件蜂鸣序列发送到客户端(使用xev或此页面末尾的源进行尝试)。
然后,qt( qtbase / src / plugins / platforms / xcb / qxcbkeyboard.cpp )尝试从这些事件中找出其是否是自动重复的情况:收到发行版时,它使用先行功能来确定是否先后自动按下(时间戳足够接近),并且如果是,则假定为自动重复。
这并不总是有效,至少在所有平台上也是如此。 对于我的情况(旧的和用完的慢速笔记本电脑(运行ubuntu 16.04的Intel®Celeron(R)CPU N2830 @ 2.16GHz×2)),它有助于在检查之前将睡眠状态设置为(500),从而允许发布后的新闻发布会事件到达...大约在qxcbkeyboard.cpp的1525行:
// look ahead for auto-repeat
KeyChecker checker(source->xcb_window(), code, time, state);
usleep(500); // Added, 100 is to small, 200 is ok (for me)
xcb_generic_event_t *event = connection()->checkEvent(checker);
if (event) {
...
归档为QTBUG-57335 。
Nb:X的行为可以通过使用来更改
Display *dpy=...;
Bool result;
XkbSetDetectableAutoRepeat (dpy, true, &result);
然后,在按住键的情况下,它不会发送此释放按顺序,但是使用它会需要对autorepeat-detection-logic进行更多更改。
无论如何解决了。
问题是我有一个小部件,它是QGLWidget的子类,用于显示Kinect的一些增强现实图像。 每当按下键盘按钮时,此小部件都会接管键盘焦点。
为了解决这个问题,我需要从MainWindow
类( MainWindow
是QMainWindow
的子类)中调用grabKeyboard
函数,因此this->grabKeyboard()
是按下key_0
按钮时需要添加的行,这样MainWindow
不会丢失键盘焦点,然后释放键时,我需要添加此行- this->releaseKeyboard()
以恢复正常行为,也就是说,其他小部件可以具有键盘焦点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.