QKeyEvent isAutoRepeat not working?

QKeyEvent isAutoRepeat not working?

本文关键字:working not isAutoRepeat QKeyEvent      更新时间:2023-10-16

所以,我有一个应用程序,如果一个特定的按钮保持按下它播放音频设备,当按钮被释放它停止音频设备。我使用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 pressedkey_0 released,尽管我没有在按下0键后释放它。是我的代码错了还是别的什么东西错了?

谢谢。

编辑

我认为这是因为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)试图从这些事件中找出它是否是自动重复的情况:当收到一个发布时,它使用一个向前看的功能来确定它后面是否有一个按(时间戳足够接近),如果是这样,它假设自动重复。

这并不总是有效,至少不是在所有平台上。对于我的情况(旧的和过时的慢笔记本电脑(英特尔®赛扬(R) CPU N2830 @ 2.16GHz × 2)运行ubuntu 16.04),它有助于在检查之前设置ussleep(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);

那么它不会在按住键的情况下发送这个release-press-sequences,但是使用它将需要对autorepeat-detection-logic进行更多的更改。

反正解决了。

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

为了解决这个问题,我需要从MainWindow类调用grabKeyboard函数(MainWindowQMainWindow的子类),因此this->grabKeyboard()是我需要在key_0按钮按下时添加的行,以便MainWindow不会失去键盘焦点,然后当键被释放时,我需要添加行this->releaseKeyboard()以恢复正常行为,也就是说,其他小部件可以具有键盘焦点。