Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. Q: Qt - [c++] PropertyAnimation from WorkerThread
Forum Updated to NodeBB v4.3 + New Features

Q: Qt - [c++] PropertyAnimation from WorkerThread

Scheduled Pinned Locked Moved Solved Game Development
7 Posts 4 Posters 1.0k 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.
  • K Offline
    K Offline
    kevin_d
    wrote on last edited by
    #1

    Hi everyone!

    I am using a QPropertyAnimation from within a QFuture.
    Unfortunately, my program dies from time to time, stating the following:

    QObject::startTimer: Timers can only be used with threads started with QThread
    QBasicTimer::start: Timers cannot be started from another thread
    QPropertyAnimation::updateState (): Changing state of an animation without target
    

    How can i make the PropertyAnimation thread-safe?

    best regards, kevin

    BondrusiekB jeremy_kJ 2 Replies Last reply
    0
    • K kevin_d

      Hi everyone!

      I am using a QPropertyAnimation from within a QFuture.
      Unfortunately, my program dies from time to time, stating the following:

      QObject::startTimer: Timers can only be used with threads started with QThread
      QBasicTimer::start: Timers cannot be started from another thread
      QPropertyAnimation::updateState (): Changing state of an animation without target
      

      How can i make the PropertyAnimation thread-safe?

      best regards, kevin

      BondrusiekB Offline
      BondrusiekB Offline
      Bondrusiek
      wrote on last edited by
      #2

      @kevin_d Please, paste the suspicious code. Other users can use this code and find a solution.

      1 Reply Last reply
      0
      • K kevin_d

        Hi everyone!

        I am using a QPropertyAnimation from within a QFuture.
        Unfortunately, my program dies from time to time, stating the following:

        QObject::startTimer: Timers can only be used with threads started with QThread
        QBasicTimer::start: Timers cannot be started from another thread
        QPropertyAnimation::updateState (): Changing state of an animation without target
        

        How can i make the PropertyAnimation thread-safe?

        best regards, kevin

        jeremy_kJ Online
        jeremy_kJ Online
        jeremy_k
        wrote on last edited by
        #3

        @kevin_d said in Q: Qt - [c++] PropertyAnimation from WorkerThread:

        Hi everyone!

        I am using a QPropertyAnimation from within a QFuture.
        Unfortunately, my program dies from time to time, stating the following:

        QObject::startTimer: Timers can only be used with threads started with QThread
        QBasicTimer::start: Timers cannot be started from another thread
        QPropertyAnimation::updateState (): Changing state of an animation without target
        

        How can i make the PropertyAnimation thread-safe?

        It's not clear whether the C++ QPropertyAnimation or QML PropertyAnimation is under discussion. Either way, the simple explanation is that neither class can be used from a different thread than the target object.

        Reading https://doc.qt.io/qt-6/threads-qobject.html explains why and may reveal some options for this use case. It also helps to explain the first warning: QtConcurrent threads have no event dispatcher, and therefore can't play host to a timer.

        Answering the question, make a property animation safe by not using it with threads. Threads are frequently unnecessary and always complicate a program's logic.

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

        1 Reply Last reply
        1
        • K Offline
          K Offline
          kevin_d
          wrote on last edited by
          #4

          Hello!

          Sorry for the delay and thanks for answering.

          I am using a QPropertyAnimation to move the Camera on a Qt3D scene during a sequence, triggered in a QFuture.

          1. Move the camera upwards (QPropertyAnimation on the Camera)
          2. Wait for the animation to finish : QThread::msleep(1000)
          3. Place a figure
          4. Move the camera back down
          5. Wait for the Animation to finish : QThread::msleep(1000)
          6. Release a semaphore to trigger waiting action
          futureSwitch = QtConcurrent::run([this, party]
              {
                  semAnimation->acquire();
                  QThread::msleep(300);
                  MoveCameraToTop();
                  QThread::msleep(400);
                  DropFigure();
                  QThread::msleep(600);
                  MoveCameraToBottom();
                  QThread::msleep(1800);
                  return 1;
              });
          

          Animation:

          void MoveCameraToBottom()
          {
              // class CameraAnimation : public QPropertyAnimation
              camPosAnimation = new CameraAnimation(camera, 
                      CameraAnimation::CamPropertyType::Position);
          
              camPosAnimation->setParent(obj);
              camPosAnimation->startPos = pos_start;
              camPosAnimation->endPos = position;
              camPosAnimation->trigger();
          }
          

          Why using a future for the animation sequence?
          ... because when triggered in the main thread, the UI does not update the scene, and animations are not updating live (especially with QThread::msleep()).

          JonBJ jeremy_kJ 2 Replies Last reply
          0
          • K kevin_d

            Hello!

            Sorry for the delay and thanks for answering.

            I am using a QPropertyAnimation to move the Camera on a Qt3D scene during a sequence, triggered in a QFuture.

            1. Move the camera upwards (QPropertyAnimation on the Camera)
            2. Wait for the animation to finish : QThread::msleep(1000)
            3. Place a figure
            4. Move the camera back down
            5. Wait for the Animation to finish : QThread::msleep(1000)
            6. Release a semaphore to trigger waiting action
            futureSwitch = QtConcurrent::run([this, party]
                {
                    semAnimation->acquire();
                    QThread::msleep(300);
                    MoveCameraToTop();
                    QThread::msleep(400);
                    DropFigure();
                    QThread::msleep(600);
                    MoveCameraToBottom();
                    QThread::msleep(1800);
                    return 1;
                });
            

            Animation:

            void MoveCameraToBottom()
            {
                // class CameraAnimation : public QPropertyAnimation
                camPosAnimation = new CameraAnimation(camera, 
                        CameraAnimation::CamPropertyType::Position);
            
                camPosAnimation->setParent(obj);
                camPosAnimation->startPos = pos_start;
                camPosAnimation->endPos = position;
                camPosAnimation->trigger();
            }
            

            Why using a future for the animation sequence?
            ... because when triggered in the main thread, the UI does not update the scene, and animations are not updating live (especially with QThread::msleep()).

            JonBJ Online
            JonBJ Online
            JonB
            wrote on last edited by
            #5

            @kevin_d
            So, since accessing the UI from threads is flawed, get rid of things like msleep() and do it on a QTimer in the UI thread.

            1 Reply Last reply
            2
            • K kevin_d

              Hello!

              Sorry for the delay and thanks for answering.

              I am using a QPropertyAnimation to move the Camera on a Qt3D scene during a sequence, triggered in a QFuture.

              1. Move the camera upwards (QPropertyAnimation on the Camera)
              2. Wait for the animation to finish : QThread::msleep(1000)
              3. Place a figure
              4. Move the camera back down
              5. Wait for the Animation to finish : QThread::msleep(1000)
              6. Release a semaphore to trigger waiting action
              futureSwitch = QtConcurrent::run([this, party]
                  {
                      semAnimation->acquire();
                      QThread::msleep(300);
                      MoveCameraToTop();
                      QThread::msleep(400);
                      DropFigure();
                      QThread::msleep(600);
                      MoveCameraToBottom();
                      QThread::msleep(1800);
                      return 1;
                  });
              

              Animation:

              void MoveCameraToBottom()
              {
                  // class CameraAnimation : public QPropertyAnimation
                  camPosAnimation = new CameraAnimation(camera, 
                          CameraAnimation::CamPropertyType::Position);
              
                  camPosAnimation->setParent(obj);
                  camPosAnimation->startPos = pos_start;
                  camPosAnimation->endPos = position;
                  camPosAnimation->trigger();
              }
              

              Why using a future for the animation sequence?
              ... because when triggered in the main thread, the UI does not update the scene, and animations are not updating live (especially with QThread::msleep()).

              jeremy_kJ Online
              jeremy_kJ Online
              jeremy_k
              wrote on last edited by
              #6

              @kevin_d If I understand the description, the goal is:

              1. an animation that moves the camera up
              2. an action that occurs at the end of step 1
              3. an animation that moves the camera down

              The correct way to determine when a QPropertyAnimation completes is to use the finished() signal. No sleeping, threading, semaphores, or explicit timers are required.

              QPropertyAnimation upAnimator, downAnimator;
              QObject::connect(&upAnimator, &QAbstractAnimation::finished, &midpoint);
              QObject::connect(&downAnimator, &QAbstractAnimation::finished, []() { qDebug() << "Done!"; });
              
              void beginAnimation() {
                  upAnimator.start();
              }
              
              void midpoint() {
                  DropFigure();
                  downAnimator.start();
              }
              

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

              1 Reply Last reply
              3
              • K Offline
                K Offline
                kevin_d
                wrote on last edited by
                #7

                Thank you. This way the application is clearly more stable.

                This works also fine, when i wait for all the animations:

                QEventLoop loopPos;
                connect(myAnimation, &QParallelAnimationGroup::finished, &loopPos, &QEventLoop::quit );
                loopPos.exec();
                

                ... and if needed use a

                QParallelAnimationGroup
                

                best regards!

                1 Reply Last reply
                0
                • K kevin_d has marked this topic as solved on

                • Login

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