A problem with QWidget update
-
Hi comrades,
I have a problem when I use QWidget to load a image. In my project, there is a thread that processes the images captured by the camera, finally it will scale last frame of image and emit a qt signal to tell the main thread to refresh. It looks like:QObject::connect(this, &VideoWidget::requestUpdate, this, this { update(); }, Qt::ConnectionType::QueuedConnection);
But it was only three or four hours behaved normally, I kept my exe running all night, but it can not receive QEvent::Paint any more in next day, and if I click another button, the VideoWidget will refresh again! Since this phenomenon has been happening for a long time, I did a debug version comparison on another computer, The machine was running fine in the morning.
Finally, both computers are on Windows, the Qt version is 5.12.10.
-
A QWidget alone will not display an image. How is an image being rendered?
This:
QObject::connect(this, &VideoWidget::requestUpdate, this, this { update(); }, Qt::ConnectionType::QueuedConnection);
Makes no sense to me. You are connecting a signal from
this
to a (malformed?) lambda withthis
as its context. The signal and slot are in the same object and therefore strike me as being explicitly in the same thread. So, no need for a queued connection or, indeed, a signal-slot connection at all.(QWidget::update() is already a slot so It's not clear why a lambda should be needed here.)
Perhaps you can provide more context including more of your actual compiling code (and enclose it in triple backticks)
```
your code
``` -
@ChrisW67 Thank you for your reply! As you said, the signal emitter and slot receiver are same object(this), but it really emit this custom signal in a child thread, the purpose of using this signal-slot is to be able to call QWidget::update on the main thread. About painting a image, it just use QPainter::drawImage in a override paintEvent(QPaintEvent* event).
-
@Assaber said in A problem with QWidget update:
the signal emitter and slot receiver are same object(this), but it really emit this custom signal in a child thread
An object can only live in one thread, so what you wrote is simply not possible. Or your description is not clear.
"the purpose of using this signal-slot is to be able to call QWidget::update on the main thread" - then why do you connect the signal to a slot in same object, which, according to your description, is living in a child thread? The slot will be executed in child thread.
-
@jsulm I can not upload full code, but if class Snow inherited from QObject and exist Q_OBJECT, the following code can works
Snow(QObject* parent) : QObject(parent) { mWorkThread = std::make_shared<std::thread>([this]() { while (mWorkThreadEnable) { emit this->heartbeat(); std::cout << "> ping[" << std::this_thread::get_id() << "]" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); } }); QObject::connect(this, &Snow::heartbeat, this, [this]() { std::this_thread::sleep_for(std::chrono::milliseconds(100)); // For the sake of cout looks normal std::cout << "< pong[" << std::this_thread::get_id() << "]" << std::endl; }); };
-
Why use threads at all?
#include <QCoreApplication> #include <QTimer> #include <QDebug> class Snow: public QObject { Q_OBJECT public: explicit Snow(QObject *parent = nullptr): QObject(parent) { m_pingTimer = new QTimer(this); m_pingTimer->setInterval(1000); connect(m_pingTimer, &QTimer::timeout, this, &Snow::handlePing); } ~Snow() { } void setPingEnable(bool enable) { if (enable) { m_pingTimer->start(); } else { m_pingTimer->stop(); } } private slots: void handlePing() { qDebug() << "ping" << Q_FUNC_INFO; QTimer::singleShot(100, this, &Snow::handlePong); } void handlePong() { qDebug() << "pong" << Q_FUNC_INFO; } private: QTimer *m_pingTimer; }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); Snow snow; snow.setPingEnable(true); // only run a while QTimer::singleShot(10000l, &app, &QCoreApplication::quit); return app.exec(); } #include "main.moc"