QPushButton cannot be released
-
I did a time-consuming operation in the button_1 slot function. In order to avoid the interface losing response, use QApplication: : processEvents (). However, if the button_2 is keep pressed during the while(time.elapsed() < 2000), the button_2 cannot be released after the while is over.
Note: There is no problem with the way you use the mouse to click, but there is a problem with the way you use the touch.This is the cpp file:
#include "widget.h" #include <QTime> #include <QPushButton> #include <QApplication> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) { button_1 = new QPushButton("QPushButton 1", this); button_2 = new QPushButton("QPushButton 2", this); button_1->setGeometry(50, 100, 200, 200); button_2->setGeometry(300, 100, 200, 200); resize(600, 400); connect(button_1, &QPushButton::clicked, this, &Widget::pushButton1Click); } Widget::~Widget() { } void Widget::pushButton1Click() { qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<< ""; QTime time; time.start(); while(time.elapsed() < 2000) QApplication::processEvents(); qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<< ""; }
This is the header file:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> class QPushButton; class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: QPushButton *button_1; QPushButton *button_2; private slots: void pushButton1Click(); }; #endif // WIDGET_H
This is the result of the run:
-
@JonB If I don't use processEvents(), that causes another problem. The program will block in the while loop, and the interface will become unresponsive, unable to press the button_2.
@MoonBrid again: fix your design and don't block the main event loop. Do heavy computing stuff in separate threads.
-
I did a time-consuming operation in the button_1 slot function. In order to avoid the interface losing response, use QApplication: : processEvents (). However, if the button_2 is keep pressed during the while(time.elapsed() < 2000), the button_2 cannot be released after the while is over.
Note: There is no problem with the way you use the mouse to click, but there is a problem with the way you use the touch.This is the cpp file:
#include "widget.h" #include <QTime> #include <QPushButton> #include <QApplication> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) { button_1 = new QPushButton("QPushButton 1", this); button_2 = new QPushButton("QPushButton 2", this); button_1->setGeometry(50, 100, 200, 200); button_2->setGeometry(300, 100, 200, 200); resize(600, 400); connect(button_1, &QPushButton::clicked, this, &Widget::pushButton1Click); } Widget::~Widget() { } void Widget::pushButton1Click() { qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<< ""; QTime time; time.start(); while(time.elapsed() < 2000) QApplication::processEvents(); qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<< ""; }
This is the header file:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> class QPushButton; class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: QPushButton *button_1; QPushButton *button_2; private slots: void pushButton1Click(); }; #endif // WIDGET_H
This is the result of the run:
@MoonBrid said in QPushButton cannot be released:
while(time.elapsed() < 2000) QApplication::processEvents();
This is way too busy a loop. Put in a reasonable test or try calling
processEvents()
much less often, e.g.if (time.elapsed() % 100 == 0)
, and see if that helps.Calling
processEvents()
because you are doing a "busy" calculation and want to "avoid the interface losing response," is evil and a bad pattern. If this is ultimately the problem (or you want to write better Qt code) change over to a proper pattern, like doing limited "chunks" of work over time from aQTimer
or use a worker thread.Qt does have a concept of different, "nested" event loops. Your
processEvents()
is not at the same "level" as the base event loop processor. It is possible that something about button release needs to be processed at the same level as the button press. I am not sure about this, and whether it applies to your case, but it could be a factor. -
@MoonBrid said in QPushButton cannot be released:
while(time.elapsed() < 2000) QApplication::processEvents();
This is way too busy a loop. Put in a reasonable test or try calling
processEvents()
much less often, e.g.if (time.elapsed() % 100 == 0)
, and see if that helps.Calling
processEvents()
because you are doing a "busy" calculation and want to "avoid the interface losing response," is evil and a bad pattern. If this is ultimately the problem (or you want to write better Qt code) change over to a proper pattern, like doing limited "chunks" of work over time from aQTimer
or use a worker thread.Qt does have a concept of different, "nested" event loops. Your
processEvents()
is not at the same "level" as the base event loop processor. It is possible that something about button release needs to be processed at the same level as the button press. I am not sure about this, and whether it applies to your case, but it could be a factor.@JonB Thank you for your reply. I tried if (time.elapsed() % 100 == 0) and if (time.elapsed() % 1000 == 0), but it didn't work.
From the source:”src/gui/kernel/qguiapplication.cpp“
void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e) { ... switch (touchPoint.state()) { ... case Qt::TouchPointReleased: w = touchInfo.window; ///< test remove // if (!w) // continue; ///< test add if (!w) { // determine which window this event will go to if (!window) window = QGuiApplication::topLevelAt(touchPoint.screenPos().toPoint()); if (!window) continue; w = window; } ... } ... if (windowsNeedingEvents.isEmpty()) return; ... }
This is because the windowsNeedingEvents. IsEmpty , so it return. And my test code can solve my problem. But I don't want to change the source code for fear of causing other problems.
-
@JonB Thank you for your reply. I tried if (time.elapsed() % 100 == 0) and if (time.elapsed() % 1000 == 0), but it didn't work.
From the source:”src/gui/kernel/qguiapplication.cpp“
void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e) { ... switch (touchPoint.state()) { ... case Qt::TouchPointReleased: w = touchInfo.window; ///< test remove // if (!w) // continue; ///< test add if (!w) { // determine which window this event will go to if (!window) window = QGuiApplication::topLevelAt(touchPoint.screenPos().toPoint()); if (!window) continue; w = window; } ... } ... if (windowsNeedingEvents.isEmpty()) return; ... }
This is because the windowsNeedingEvents. IsEmpty , so it return. And my test code can solve my problem. But I don't want to change the source code for fear of causing other problems.
-
@MoonBrid
Are you saying there is a problem because you callprocessEvents()
, or are you saying it never works? If the former, so did you try getting rid ofprocessEvents()
as suggested? -
@JonB processEvents() is working normally, durind the while , I can press button_2.For some reason, I can't give up using processEvent().And the mouse doesn't have this problem, but the touch does, whether it's a bug?
@MoonBrid said in QPushButton cannot be released:
For some reason, I can't give up using processEvent()
Fix your design. You already found out the reason. Noone will change this.
-
@JonB processEvents() is working normally, durind the while , I can press button_2.For some reason, I can't give up using processEvent().And the mouse doesn't have this problem, but the touch does, whether it's a bug?
-
@MoonBrid said in QPushButton cannot be released:
I can't give up using processEvent()
The question was, if you do not do
processEvents()
does it then work or still go wrong? -
@JonB If I don't use processEvents(), that causes another problem. The program will block in the while loop, and the interface will become unresponsive, unable to press the button_2.
@MoonBrid again: fix your design and don't block the main event loop. Do heavy computing stuff in separate threads.
-
@JonB If I don't use processEvents(), that causes another problem. The program will block in the while loop, and the interface will become unresponsive, unable to press the button_2.
@MoonBrid said in QPushButton cannot be released:
@JonB If I don't use processEvents(), that causes another problem. The program will block in the while loop, and the interface will become unresponsive, unable to press the button_2.
Sorry, I give up. That is not what I asked you. I have asked/suggested more than once that you remove the
processEvents()
and then tell us whether the behaviour of holding the button down during the 2 seconds and then releasing it afterwards does or does not recognise the button up. That is all you had to try. I don't understand why it's so difficult to try something while you diagnose. No more from me now. -