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. Why does QTimer::setInterval(0) not work as expected in Qt 6?
Forum Updated to NodeBB v4.3 + New Features

Why does QTimer::setInterval(0) not work as expected in Qt 6?

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 4 Posters 166 Views 2 Watching
  • 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.
  • S Offline
    S Offline
    summit
    wrote last edited by summit
    #1

    I have a QTimer in a QOpenGLWidget constructor to call update() continuously:

    connect(&timer, &QTimer::timeout, this, [&]() {
        update();
    });
    timer.setTimerType(Qt::PreciseTimer);
    timer.setInterval(0); // This worked in Qt 5 with QGLWidget
    timer.start();
    

    In Qt 5 QGLWidget, setting the interval to 0 made the timer fire as fast as possible. In Qt 6, i get FPS as NAN, and I have to set it to 1 to make it work:

    timer.setInterval(1); // Required in Qt 6
    
    GLWidget::GLWidget(QWidget* parent) : QOpenGLWidget(parent)
    {
    	connect(&timer, &QTimer::timeout, this, [&]() {
    		update();
    		qint64 now = elapsedtimer.elapsed();
    		qint64 elapsed = now - prevTime;
    		prevTime = now;
    
    		float fps = 1000.0f / elapsed;
    		wavefrontAccess->SetFps(QString::number(fps));
    		});
    
    	timer.setTimerType(Qt::PreciseTimer);
    	timer.setInterval(1);
    	timer.start();
    
    }
    
    1 Reply Last reply
    0
    • S Offline
      S Offline
      summit
      wrote last edited by summit
      #5

      @jeremy_k @Christian-Ehrlicher @Kent-Dorfman The timer was being fired two times once with 20ms elapsed and once with 0 ms Elapsed time.
      Previously in QT 5 with QGlWidget , i was using the same code for timer with no issues at all.

      For QT 6 with QopenglWidget this is what i had to do.

      class GLWidget : public QOpenGLWidget
      {
      	Q_OBJECT;
      public:
      	explicit GLWidget(QWidget *parent = 0);
      	void initializeGL() override;
      	void paintGL() override;
      	void RenderLoop();
      	void resizeGL(int w, int h) override;
      	void animate();
      		
      	qint64 m_lastTime = 0;
      	int   m_frameCount = 0;
      	float m_fps = 0.0f;
      
      	QElapsedTimer m_elapsedTimer;
      
      protected:                
      	void showEvent(QShowEvent*) override;
      

      I had to get rid of the Timer.

      GLWidget::GLWidget(QWidget* parent) : QOpenGLWidget(parent)
      {
      	
      
      }
      
      void GLWidget::paintGL()
      {
        // Do Opengl Rendering
         animate();
      }
      
      
      void GLWidget::animate()
      {
      	float deltaTimeSec = m_elapsedTimer.restart() / 1000.0f;
      	static int frameCounter = 0;
      	frameCounter++;
      
      	if (frameCounter >= 10) {  // every 10th frame (~5 times/sec at 50 FPS)
      		float fps = 1.0f / deltaTimeSec;
      		wavefrontAccess->SetFps(QString::number(fps, 'f', 2));
      		frameCounter = 0;
      	}
      
      	update();  // keep loop running
      }
      
      void GLWidget::showEvent(QShowEvent*)
      {
      	update();  // Start the loop once
      }
      
      1 Reply Last reply
      0
      • Christian EhrlicherC Online
        Christian EhrlicherC Online
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote last edited by
        #2

        You divide by zero so you get NaN. See the documentation of QTimer. A timeout of 0 exexcutes as soon as possible which can also mean directly.

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        jeremy_kJ 1 Reply Last reply
        5
        • Christian EhrlicherC Christian Ehrlicher

          You divide by zero so you get NaN. See the documentation of QTimer. A timeout of 0 exexcutes as soon as possible which can also mean directly.

          jeremy_kJ Offline
          jeremy_kJ Offline
          jeremy_k
          wrote last edited by
          #3

          @Christian-Ehrlicher said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

          You divide by zero so you get NaN. See the documentation of QTimer. A timeout of 0 exexcutes as soon as possible which can also mean directly.

          What does directly mean here? In a C++ program, the event loop needs to run in order to deliver timer events, even for a direct connection to a zero timer.
          PyQt and PySide have mechanisms that delivers events while the interactive interpreter is waiting for input, but the code presented doesn't appear to be python.

          I agree that divide by zero (or other unexpected condition) is a likely problem. prevTime doesn't have an obvious initialization before the first calculation of elapsed. There is also nothing to suggest that elapsedtimer.elapsed() can't return the same value twice.

          Asking a question about code? http://eel.is/iso-c++/testcase/

          Christian EhrlicherC 1 Reply Last reply
          0
          • Kent-DorfmanK Offline
            Kent-DorfmanK Offline
            Kent-Dorfman
            wrote last edited by
            #4

            I'd also do the the connect() AFTER setting the timer params.

            I light my way forward with the fires of all the bridges I've burned behind me.

            1 Reply Last reply
            0
            • S Offline
              S Offline
              summit
              wrote last edited by summit
              #5

              @jeremy_k @Christian-Ehrlicher @Kent-Dorfman The timer was being fired two times once with 20ms elapsed and once with 0 ms Elapsed time.
              Previously in QT 5 with QGlWidget , i was using the same code for timer with no issues at all.

              For QT 6 with QopenglWidget this is what i had to do.

              class GLWidget : public QOpenGLWidget
              {
              	Q_OBJECT;
              public:
              	explicit GLWidget(QWidget *parent = 0);
              	void initializeGL() override;
              	void paintGL() override;
              	void RenderLoop();
              	void resizeGL(int w, int h) override;
              	void animate();
              		
              	qint64 m_lastTime = 0;
              	int   m_frameCount = 0;
              	float m_fps = 0.0f;
              
              	QElapsedTimer m_elapsedTimer;
              
              protected:                
              	void showEvent(QShowEvent*) override;
              

              I had to get rid of the Timer.

              GLWidget::GLWidget(QWidget* parent) : QOpenGLWidget(parent)
              {
              	
              
              }
              
              void GLWidget::paintGL()
              {
                // Do Opengl Rendering
                 animate();
              }
              
              
              void GLWidget::animate()
              {
              	float deltaTimeSec = m_elapsedTimer.restart() / 1000.0f;
              	static int frameCounter = 0;
              	frameCounter++;
              
              	if (frameCounter >= 10) {  // every 10th frame (~5 times/sec at 50 FPS)
              		float fps = 1.0f / deltaTimeSec;
              		wavefrontAccess->SetFps(QString::number(fps, 'f', 2));
              		frameCounter = 0;
              	}
              
              	update();  // keep loop running
              }
              
              void GLWidget::showEvent(QShowEvent*)
              {
              	update();  // Start the loop once
              }
              
              1 Reply Last reply
              0
              • S summit has marked this topic as solved
              • jeremy_kJ jeremy_k

                @Christian-Ehrlicher said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                You divide by zero so you get NaN. See the documentation of QTimer. A timeout of 0 exexcutes as soon as possible which can also mean directly.

                What does directly mean here? In a C++ program, the event loop needs to run in order to deliver timer events, even for a direct connection to a zero timer.
                PyQt and PySide have mechanisms that delivers events while the interactive interpreter is waiting for input, but the code presented doesn't appear to be python.

                I agree that divide by zero (or other unexpected condition) is a likely problem. prevTime doesn't have an obvious initialization before the first calculation of elapsed. There is also nothing to suggest that elapsedtimer.elapsed() can't return the same value twice.

                Christian EhrlicherC Online
                Christian EhrlicherC Online
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote last edited by
                #6

                @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                the event loop needs to run in order to deliver timer events, even for a direct connection to a zero timer.

                Why? Where did you read this?

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                jeremy_kJ 1 Reply Last reply
                0
                • Christian EhrlicherC Christian Ehrlicher

                  @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                  the event loop needs to run in order to deliver timer events, even for a direct connection to a zero timer.

                  Why? Where did you read this?

                  jeremy_kJ Offline
                  jeremy_kJ Offline
                  jeremy_k
                  wrote last edited by
                  #7

                  @Christian-Ehrlicher said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                  @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                  the event loop needs to run in order to deliver timer events, even for a direct connection to a zero timer.

                  Why? Where did you read this?

                  My first introduction to the topic was the zero timer autotest.

                  Asking a question about code? http://eel.is/iso-c++/testcase/

                  Christian EhrlicherC 1 Reply Last reply
                  0
                  • jeremy_kJ jeremy_k

                    @Christian-Ehrlicher said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                    @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                    the event loop needs to run in order to deliver timer events, even for a direct connection to a zero timer.

                    Why? Where did you read this?

                    My first introduction to the topic was the zero timer autotest.

                    Christian EhrlicherC Online
                    Christian EhrlicherC Online
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote last edited by Christian Ehrlicher
                    #8

                    @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                    My first introduction to the topic

                    ... should be the documentation.
                    And if you really want to know more than look into the source: https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qtimer.cpp#n368

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    jeremy_kJ 1 Reply Last reply
                    0
                    • Christian EhrlicherC Christian Ehrlicher

                      @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                      My first introduction to the topic

                      ... should be the documentation.
                      And if you really want to know more than look into the source: https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qtimer.cpp#n368

                      jeremy_kJ Offline
                      jeremy_kJ Offline
                      jeremy_k
                      wrote last edited by
                      #9

                      @Christian-Ehrlicher said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                      @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                      My first introduction to the topic

                      ... should be the documentation.

                      I thought you were going to ask for something hard, like a reference within the implementation.

                      In search of firm wording, there's this:
                      https://doc.qt.io/qt-6/qtimer.html#details

                      As a special case, a QTimer with a timeout of 0 will time out as soon as possible, though the ordering between zero timers and other sources of events is unspecified. Zero timers can be used to do some work while still providing a snappy user interface

                      This also hints at the event loop reliance:
                      https://doc.qt.io/qt-6/qtimer.html#interval-prop

                      A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.

                      If a zero timer was implemented as a direct function call, eg:

                      void QTimer::start()
                      {
                          if (this->interval() == 0)
                              emit timeout();
                      }
                      

                      then it wouldn't make sense to say that the ordering was unspecified. The timer would time out before QTimer::start() returned. Further, they would be unsuitable to do some work while still providing a snappy user interface, because they would preempt the starting of, or a return to the event loop. The code might as well perform this work directly.

                      Finally (finally?), a repeating zero timer could deadlock the system. Eg:

                      QTimer t1;
                      t1.setInterval(0);
                      t1.setSingleShot(false);
                      QObject::connect(&t1, &QTimer::timeout, [] { qDebug() << "zero timer"; });
                      t1.start();
                      qDebug() << "This would be an unreachable statement";
                      

                      Asking a question about code? http://eel.is/iso-c++/testcase/

                      Christian EhrlicherC 1 Reply Last reply
                      0
                      • jeremy_kJ jeremy_k

                        @Christian-Ehrlicher said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                        @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                        My first introduction to the topic

                        ... should be the documentation.

                        I thought you were going to ask for something hard, like a reference within the implementation.

                        In search of firm wording, there's this:
                        https://doc.qt.io/qt-6/qtimer.html#details

                        As a special case, a QTimer with a timeout of 0 will time out as soon as possible, though the ordering between zero timers and other sources of events is unspecified. Zero timers can be used to do some work while still providing a snappy user interface

                        This also hints at the event loop reliance:
                        https://doc.qt.io/qt-6/qtimer.html#interval-prop

                        A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.

                        If a zero timer was implemented as a direct function call, eg:

                        void QTimer::start()
                        {
                            if (this->interval() == 0)
                                emit timeout();
                        }
                        

                        then it wouldn't make sense to say that the ordering was unspecified. The timer would time out before QTimer::start() returned. Further, they would be unsuitable to do some work while still providing a snappy user interface, because they would preempt the starting of, or a return to the event loop. The code might as well perform this work directly.

                        Finally (finally?), a repeating zero timer could deadlock the system. Eg:

                        QTimer t1;
                        t1.setInterval(0);
                        t1.setSingleShot(false);
                        QObject::connect(&t1, &QTimer::timeout, [] { qDebug() << "zero timer"; });
                        t1.start();
                        qDebug() << "This would be an unreachable statement";
                        
                        Christian EhrlicherC Online
                        Christian EhrlicherC Online
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote last edited by
                        #10

                        @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                        I thought you were going to ask for something hard, like a reference within the implementation.

                        Please look at my link to the source code.

                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                        Visit the Qt Academy at https://academy.qt.io/catalog

                        jeremy_kJ 1 Reply Last reply
                        0
                        • Christian EhrlicherC Christian Ehrlicher

                          @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                          I thought you were going to ask for something hard, like a reference within the implementation.

                          Please look at my link to the source code.

                          jeremy_kJ Offline
                          jeremy_kJ Offline
                          jeremy_k
                          wrote last edited by
                          #11

                          @Christian-Ehrlicher said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                          @jeremy_k said in Why does QTimer::setInterval(0) not work as expected in Qt 6?:

                          I thought you were going to ask for something hard, like a reference within the implementation.

                          Please look at my link to the source code.

                          I overlooked that. Thanks.

                          QTimer::singleShotImpl() uses a queued connection for the ns == 0 case.

                          https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/kernel/qtimer.cpp#n389

                                  QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj,
                                          Qt::QueuedConnection, h.parameterCount(), h.parameters.data(), h.typeNames.data(),
                                          h.metaTypes.data());
                          

                          Asking a question about code? http://eel.is/iso-c++/testcase/

                          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