简体   繁体   中英

QKeyEvent isAutoRepeat not working?

So, I have an application where if a particular button is kept pressed it plays an audio device, when the button is released it stops the audio device. I use keyPressEvent and KeyReleaseEvent to implement this which is similar to the code below:

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);
        }
    }
}

But apparently isAutoRepeat function isn't working as I can see continuous print out of key_0 pressed and key_0 released despite the fact I haven't released the 0 key after I have pressed it. Is my code wrong or something else is wrong?

Thanks.

EDIT

I think this is happening because the MainWindow loses the keyboard focus. How can I actually find out which widget has the focus? I'm actually using some widgets when Qt::Key_0 pressed, but I thought I set all those possible widgets to Qt::NoFocus , I guess it's not working.

I'm trying to know which widget has the focus by doing the following:

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

but it always prints an empty string. How can I make it print the name of the widget which has the keyboard focus?

So as I also stumbled over this issue (and grabKeyboard didn't really help), I begun digging in qtbase. It is connected to X11 via xcb, and by default, in case of repeated keys, X11 sends for each repeated key a release-event immediately followed by a key-press-event. So holding down a key results in a sequence of XCB_BUTTON_RELEASE/XCB_BUTTON_PRESS-events beeing sent to the client (try it out with xev or the source at the end of this page ).

Then, qt ( qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp ) tries to figure out from these events whether its an autorepeat case: when a release is received, it uses a lookahead feature to figure if its followed by a press (with timestamps close enough), and if so it assumes autorepeat.

This does not always work, at least not on all platforms. For my case (old and outworn slow laptop (Intel® Celeron(R) CPU N2830 @ 2.16GHz × 2) running ubuntu 16.04), it helped to just put a usleep (500) before that check, allowing the press event following the release event to arrive... it's around line 1525 of qxcbkeyboard.cpp:

    // 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) {
    ...

Filed this as QTBUG-57335 .

Nb: The behaviour of X can be changed by using

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

Then it wont send this release-press-sequences in case of a hold down key, but using it would require more changes to the autorepeat-detection-logic.

Anyway solved it.

The problem was that I have a widget which is a subclass of QGLWidget which I use to show some augmented reality images from Kinect. This widget takes over the keyboard focus whenever a keyboard button is pressed.

To solve this problem, I needed to call grabKeyboard function from the MainWindow class ( MainWindow is a subclass of QMainWindow ), so this->grabKeyboard() is the line I needed to add when key_0 button is pressed so that MainWindow doesn't lose the keyboard focus, and then when the key is released I needed to add the line this->releaseKeyboard() to resume normal behaviour, that is, other widgets can have the keyboard focus.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM