Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. A problem with QWidget update
QtWS25 Last Chance

A problem with QWidget update

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 3 Posters 343 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Assaber
    wrote on last edited by
    #1

    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.

    1 Reply Last reply
    0
    • C Offline
      C Offline
      ChrisW67
      wrote on last edited by
      #2

      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 with this 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
      ```

      A 1 Reply Last reply
      0
      • C ChrisW67

        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 with this 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
        ```

        A Offline
        A Offline
        Assaber
        wrote on last edited by
        #3

        @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).

        jsulmJ 1 Reply Last reply
        0
        • A Assaber

          @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).

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @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.

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          A 1 Reply Last reply
          0
          • A Offline
            A Offline
            Assaber
            wrote on last edited by
            #5

            I can't reply!

            1 Reply Last reply
            0
            • jsulmJ jsulm

              @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.

              A Offline
              A Offline
              Assaber
              wrote on last edited by
              #6

              @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;
              		});
              };
              
              1 Reply Last reply
              0
              • C Offline
                C Offline
                ChrisW67
                wrote on last edited by
                #7

                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"
                
                A 1 Reply Last reply
                2
                • C ChrisW67

                  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"
                  
                  A Offline
                  A Offline
                  Assaber
                  wrote on last edited by
                  #8

                  @ChrisW67 Since this is just a simplified example, I just want to explain to that bro how one QObject works in two threads. The reason for the two threads is that I would post-process the image after receiving it from the camera's SDK and then pass it to the main thread to paint with paintEvent

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved