duplicate execution of QSpinBox arrow click when followed by long computation



  • Under Linux, clang5, Qt5.10, the following misbehaviour is quite reproducible:

    If a QSpinBox or QDoubleSpinBox is connected to a function that takes longer than about 0.5 seconds, then a single click on an up or down arrow is followed by a second incrementation and a second execution of the connected function.

    Minimal example:

    int delay = 600;
    auto* test = new QSpinBox;
    connect(test, _SLOT_(QSpinBox, valueChanged, int), [this](int val) {
            qDebug() << "GOT VALUE " << val;
            QThread::msleep(delay);
            qDebug() << "WOKE UP "; });
    

    One single click on the "up" arrow will cause the following:

    GOT VALUE 1
    [delay]
    WOKE UP
    GOT VALUE 2
    [delay]
    WOKE UP
    

    Whereas with t of about 500 or smaller, I get the expected

    GOT VALUE 1
    [delay]
    WOKE UP
    

    What could be the cause? How to further analyze?



  • If you stop it for longer it will probably increase by even more that 1.
    You are blocking the event loop before it process the QEvent::MouseButtonRelease so it behaves like if you are holding the mouse button down.
    Try:

    int delay = 600;
    auto* test = new QSpinBox;
    connect(test, QOverload<int>::of(&QSpinBox::valueChanged), test, [delay](int val) {
            qDebug() << "GOT VALUE " << val;
            QThread::msleep(delay);
            qDebug() << "WOKE UP "; }, Qt::QueuedConnection);
    


  • Try: ...

    Tried. Still incrementing twice.



  • So upon QSpinBox::valueChanged, I ought to wait for QEvent::MouseButtonRelease?

    That would have no undesirable side effects?

    Is there some example code?



  • The problem is definetly what I described but 1 event loop cycle is not enough to capture the release.
    This solves it but I agree it's ugly

    #include <QApplication>
    #include <QStyle>
    #include <QTimer>
    #include <QDebug>
    #include <QThread>
    #include <QSpinBox>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QSpinBox wid;
        QObject::connect(&wid, QOverload<int>::of(&QSpinBox::valueChanged), &wid, [&wid](int val) {
                QTimer::singleShot(1+qMax(
                    wid.style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatRate, 0, &wid)
                    ,wid.style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold, 0, &wid)
                ),&wid,[val](){
                    qDebug() << "GOT VALUE " << val;
                    QThread::msleep(600);
                    qDebug() << "WOKE UP ";
                });
    
        });
        wid.show();
        return a.exec();
    }
    

  • Moderators

    This could be the same as in QTBUG-14259


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.