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. Make a sequence of QWidget moves
Forum Update on Monday, May 27th 2025

Make a sequence of QWidget moves

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 3 Posters 234 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.
  • P Offline
    P Offline
    Peter_Dev
    wrote on last edited by
    #1

    Hi everyone! I'm making a game. There're a game field made of 64 squares (like chess) and a QPushButton with icon on it. Button supposed to move on field randomly. Problem is that when i use move() several times in a row it only displays last move:

    QPushButton->move(ax, ay);
    for(int i=0; i<10000; i++){} //for delay
    QPushButton->move(bx, by);
    for(int i=0; i<10000; i++){}
    QPushButton->move(cx, cy);
    

    only

    QPushButton->move(cx, cy);
    

    will be executed with no delay before. Just button will be on position cx, cy when i start a program.
    Same thing happens when i use QPropertyAnimation:

    QPropertyAnimation *animation = new QPropertyAnimation(ui->pushButton, "geometry");
    
        animation->setDuration(10000);
        animation->setStartValue(QRect(20, 20, 80, 80));
        animation->setEndValue(QRect(100, 20, 80, 80));
        animation->start();
    
        animation->setDuration(10000);
        animation->setStartValue(QRect(100, 20, 80, 80));
        animation->setEndValue(QRect(100, 100, 80, 80));
        animation->start();
    
        animation->setDuration(10000);
        animation->setStartValue(QRect(100, 100, 80, 80));
        animation->setEndValue(QRect(20, 100, 80, 80));
        animation->start();
    

    Only last animation will be executed.
    How can i make as many moves as i need, so when i start the game all movements would be consistently executed with any needed delay?

    KillerSmathK 1 Reply Last reply
    0
    • P Peter_Dev

      Hi everyone! I'm making a game. There're a game field made of 64 squares (like chess) and a QPushButton with icon on it. Button supposed to move on field randomly. Problem is that when i use move() several times in a row it only displays last move:

      QPushButton->move(ax, ay);
      for(int i=0; i<10000; i++){} //for delay
      QPushButton->move(bx, by);
      for(int i=0; i<10000; i++){}
      QPushButton->move(cx, cy);
      

      only

      QPushButton->move(cx, cy);
      

      will be executed with no delay before. Just button will be on position cx, cy when i start a program.
      Same thing happens when i use QPropertyAnimation:

      QPropertyAnimation *animation = new QPropertyAnimation(ui->pushButton, "geometry");
      
          animation->setDuration(10000);
          animation->setStartValue(QRect(20, 20, 80, 80));
          animation->setEndValue(QRect(100, 20, 80, 80));
          animation->start();
      
          animation->setDuration(10000);
          animation->setStartValue(QRect(100, 20, 80, 80));
          animation->setEndValue(QRect(100, 100, 80, 80));
          animation->start();
      
          animation->setDuration(10000);
          animation->setStartValue(QRect(100, 100, 80, 80));
          animation->setEndValue(QRect(20, 100, 80, 80));
          animation->start();
      

      Only last animation will be executed.
      How can i make as many moves as i need, so when i start the game all movements would be consistently executed with any needed delay?

      KillerSmathK Offline
      KillerSmathK Offline
      KillerSmath
      wrote on last edited by KillerSmath
      #2

      @Peter_Dev

      For Loop as Delay is not a good idea because it can freeze your interface. Instead, you could use a QTimer to perform certain operation at intervals.

      For Example:

      QTimer *timer = new QTimer(this);
      timer->setInterval(10000);
      connect (timer, &QTimer::timeout, [] () {
          // execute
      });
      timer->start();
      

      Considering your problem, you could use a data struture (FIFO - First In, First Out) to store and recover your movements.

      QQueue

      struct Move{
        int x, y;
      }
      
      QQueue<Move> moveQueue;
      
      moveQueue.enqueue({1,1});
      moveQueue.enqueue({2,2});
      moveQueue.enqueue({1,2});
      moveQueue.enqueue({1,1});
      
      while (!moveQueue.isEmpty()){
          const Move& move = queue.dequeue();
          qDebug() << "X: " << move.x << " - Y:" << move.y;
      }
      

      Output:
      X: 1 - Y: 1
      X: 2 - Y: 2
      X: 1 - Y: 2
      X: 1 - Y: 1


      Using the example shown above, this solution comes:

      example.gif

      mainwindow.h file

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <QQueue>
      
      namespace Ui {
      class MainWindow;
      }
      
      struct Move{ int x, y; };
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit MainWindow(QWidget *parent = 0);
          ~MainWindow();
      
      private:
          Ui::MainWindow *ui;
          QQueue<Move> moveQueue;
      };
      
      #endif // MAINWINDOW_H
      

      mainwindow.cpp

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      #include <QTimer>
      #include <QPropertyAnimation>
      
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
      
          moveQueue.enqueue({1,1});
          moveQueue.enqueue({2,2});
          moveQueue.enqueue({1,2});
          moveQueue.enqueue({1,1});
      
          QTimer *timer = new QTimer(this);
          timer->setInterval(10000);
      
          connect(timer, &QTimer::timeout, [this, timer](){
              if(moveQueue.empty()){
                  timer->stop();
                  return;
              }
      
              const Move& move = moveQueue.dequeue();
      
              QPropertyAnimation *animation = new QPropertyAnimation(ui->pushButton, "geometry");
              connect(animation, &QPropertyAnimation::finished, animation, &QPropertyAnimation::deleteLater); // auto destroy        
              animation->setDuration(1000); // 1s
              animation->setStartValue(ui->pushButton->geometry()); // actual geometry
              animation->setEndValue(QRect(80*move.x, 80*move.y, 80, 80)); // x = width * move.x | y = height * move.y
              animation->start();
          });
      
          timer->start(5000); // start after 5s
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      

      @Computer Science Student - Brazil
      Web Developer and Researcher
      “Sometimes it’s the people no one imagines anything of who do the things that no one can imagine.” - Alan Turing

      P 1 Reply Last reply
      4
      • KillerSmathK KillerSmath

        @Peter_Dev

        For Loop as Delay is not a good idea because it can freeze your interface. Instead, you could use a QTimer to perform certain operation at intervals.

        For Example:

        QTimer *timer = new QTimer(this);
        timer->setInterval(10000);
        connect (timer, &QTimer::timeout, [] () {
            // execute
        });
        timer->start();
        

        Considering your problem, you could use a data struture (FIFO - First In, First Out) to store and recover your movements.

        QQueue

        struct Move{
          int x, y;
        }
        
        QQueue<Move> moveQueue;
        
        moveQueue.enqueue({1,1});
        moveQueue.enqueue({2,2});
        moveQueue.enqueue({1,2});
        moveQueue.enqueue({1,1});
        
        while (!moveQueue.isEmpty()){
            const Move& move = queue.dequeue();
            qDebug() << "X: " << move.x << " - Y:" << move.y;
        }
        

        Output:
        X: 1 - Y: 1
        X: 2 - Y: 2
        X: 1 - Y: 2
        X: 1 - Y: 1


        Using the example shown above, this solution comes:

        example.gif

        mainwindow.h file

        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H
        
        #include <QMainWindow>
        #include <QQueue>
        
        namespace Ui {
        class MainWindow;
        }
        
        struct Move{ int x, y; };
        
        class MainWindow : public QMainWindow
        {
            Q_OBJECT
        
        public:
            explicit MainWindow(QWidget *parent = 0);
            ~MainWindow();
        
        private:
            Ui::MainWindow *ui;
            QQueue<Move> moveQueue;
        };
        
        #endif // MAINWINDOW_H
        

        mainwindow.cpp

        #include "mainwindow.h"
        #include "ui_mainwindow.h"
        
        #include <QTimer>
        #include <QPropertyAnimation>
        
        MainWindow::MainWindow(QWidget *parent) :
            QMainWindow(parent),
            ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
        
            moveQueue.enqueue({1,1});
            moveQueue.enqueue({2,2});
            moveQueue.enqueue({1,2});
            moveQueue.enqueue({1,1});
        
            QTimer *timer = new QTimer(this);
            timer->setInterval(10000);
        
            connect(timer, &QTimer::timeout, [this, timer](){
                if(moveQueue.empty()){
                    timer->stop();
                    return;
                }
        
                const Move& move = moveQueue.dequeue();
        
                QPropertyAnimation *animation = new QPropertyAnimation(ui->pushButton, "geometry");
                connect(animation, &QPropertyAnimation::finished, animation, &QPropertyAnimation::deleteLater); // auto destroy        
                animation->setDuration(1000); // 1s
                animation->setStartValue(ui->pushButton->geometry()); // actual geometry
                animation->setEndValue(QRect(80*move.x, 80*move.y, 80, 80)); // x = width * move.x | y = height * move.y
                animation->start();
            });
        
            timer->start(5000); // start after 5s
        }
        
        MainWindow::~MainWindow()
        {
            delete ui;
        }
        
        P Offline
        P Offline
        Peter_Dev
        wrote on last edited by
        #3

        @KillerSmath
        Thanks a lot for your help!
        Is there any reason behind this behavior, when only last move or animation will be displayed until i use stack?

        jsulmJ 1 Reply Last reply
        0
        • P Peter_Dev

          @KillerSmath
          Thanks a lot for your help!
          Is there any reason behind this behavior, when only last move or animation will be displayed until i use stack?

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

          @Peter_Dev Loops and long lasting operation block event loop and as long as the event loop is blocked nothing will move. So, you move, then immediately block event loop, again move and block and so on - only last move will be actually visible.

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

          P 1 Reply Last reply
          3
          • jsulmJ jsulm

            @Peter_Dev Loops and long lasting operation block event loop and as long as the event loop is blocked nothing will move. So, you move, then immediately block event loop, again move and block and so on - only last move will be actually visible.

            P Offline
            P Offline
            Peter_Dev
            wrote on last edited by
            #5

            @jsulm
            Ok, i understand.
            Thank you for explanation!

            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