0

所以,我有一个应用程序,如果按住特定按钮,它会播放音频设备,当释放按钮时,它会停止音频设备。我使用keyPressEventKeyReleaseEvent实现它,它类似于下面的代码:

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功能不起作用,因为我可以看到连续打印出来,key_0 pressed尽管key_0 released事实上我在按下 0 键后没有释放它。是我的代码错误还是其他错误?

谢谢。

编辑

我认为这是因为MainWindow失去了键盘焦点。我如何才能真正找出哪个小部件具有焦点?按下时我实际上正在使用一些小部件Qt::Key_0,但我认为我将所有这些可能的小部件设置为Qt::NoFocus,我想它不起作用。

我试图通过执行以下操作来了解哪个小部件具有焦点:

QWidget * wigdet = QApplication::activeWindow();
qDebug()<<wigdet->accessibleName()<<endl;

但它总是打印一个空字符串。如何让它打印具有键盘焦点的小部件的名称?

4

2 回答 2

3

因此,当我也偶然发现了这个问题(并且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

注意:X 的行为可以通过使用来改变

Display *dpy=...;
Bool result;
XkbSetDetectableAutoRepeat (dpy, true, &result);

然后它不会在按住键的情况下发送此释放-按下序列,但使用它需要对自动重复检测逻辑进行更多更改。

于 2016-11-27T20:29:17.550 回答
0

反正解决了。

问题是我有一个小部件,它是 QGLWidget 的子类,我用它来显示来自 Kinect 的一些增强现实图像。每当按下键盘按钮时,此小部件都会接管键盘焦点。

为了解决这个问题,我需要grabKeyboard从类中调用函数MainWindowMainWindow是的子类QMainWindow),所以this->grabKeyboard()我需要在key_0按下按钮时添加一行,MainWindow这样不会失去键盘焦点,然后在释放键时我需要添加该行this->releaseKeyboard()以恢复正常行为,即其他小部件可以拥有键盘焦点。

于 2016-06-30T11:41:37.310 回答