Qt keyPressEvent, "Hold", and keyReleaseEvent Handling with Buttons/Mouse Clicks

GrandAdmiral picture GrandAdmiral · Sep 14, 2014 · Viewed 8.1k times · Source

I am writing a Qt program to simulate a piece of hardware and I would like to simulate button press, hold, and release events. In my application, I'd like to handle input from both the keyboard and mouse clicks to make things convenient to the user (i.e. me). I've noticed some odd behavior and I don't understand it.

The application uses QPushButton with autoRepeat enabled and a 100 ms autoRepeatDelay and autoRepeatInterval. If I mouse click on a button, I receive alternating "pressed" and "released" events. I would have expected to see 1 to N-1 "pressed" events followed by a "released" event. Why is Qt behaving that way?

I've also implemented the following code to handle button presses from the keyboard:

void MyApp::keyPressEvent(QKeyEvent *event)
{
    QString s = QString("My PRESS key is %1. The counter is %2").arg(event->text(), QString::number(keyCounter));
    qDebug() << s;
    keyCounter++;
}

void MyApp::keyReleaseEvent(QKeyEvent *event)
{
    QString s = QString("My RELEASE key is %1. The counter is %2").arg(event->text(), QString::number(keyCounter));
    qDebug() << s;
    keyCounter = 0;
}

bool MyApp::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        this->keyPressEvent(dynamic_cast<QKeyEvent*>(event));
        return true;
    }
    else if (event->type() == QEvent::KeyRelease)
    {
        this->keyReleaseEvent(dynamic_cast<QKeyEvent*>(event));
        return  true;
    }
    else
    {
        return QObject::eventFilter(obj, event);
    }
}

Here I see two types of behavior. For alphanumeric keys, I see the alternating "pressed" and "released" events. For arrow keys, I only see the "released" events. Again, I would have expected to see 1 to N-1 "pressed" events followed by a "released" event. Why do the arrow keys behave differently than the alphanumeric keys?

Is what I'm trying to do possible in Qt?

Answer

GrandAdmiral picture GrandAdmiral · Sep 17, 2014

Here was my solution: First I disabled autoRepeat and stopped handling keyPressEvents because I found that the arrow keys weren't generating them. Instead I registered shortcuts for the keyboard buttons I wanted to use:

QShortcut *shortcutUp = new QShortcut(QKeySequence("Up"), this);
QObject::connect(shortcutUp, SIGNAL(activated()), this, SLOT(on_upButton_pressed()));
shortcutUp->setAutoRepeat(false);

Then in the on_upButton_pressed() function (for example) I set a flag indicating the button was pressed. This flag is cleared in the on_upButton_released() function. That flag is checked on a 100 ms interval (using a QTimer). If the flag is true, I call on_upButton_pressed() again. This means:

  • Each mouse click or keyboard button press generates one "Press" event
  • The "Press" event sets a flag that is checked by a QTimer
  • If the flag is true, another "Press" event is generated
  • When the mouse or keyboard button is released, the "Release" event is generated and the flag is cleared.

It's working now.