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. How can I change my screen in my GUI application when a thread stops running.
Forum Updated to NodeBB v4.3 + New Features

How can I change my screen in my GUI application when a thread stops running.

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 3 Posters 542 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.
  • R Offline
    R Offline
    RoBlox
    wrote on last edited by RoBlox
    #1

    these are my files:
    navthread.h

    #pragma once
    
    #include <QObject>
    #include <QThread>
    #include <QtCore>
    
    class NavThread : public QThread
    {
      Q_OBJECT
    public:
      explicit NavThread(QObject *parent = 0);
      bool Stop;
      void run();
      bool active;
      int i;
    
    signals:
      void over();
    
    public slots:
    
    private:
      QMutex mutex;
    
    };
    

    navthread.cpp

    
    
    void NavThread::run()
    {
        ros::NodeHandle ros_nh; // Start the roscpp node by creating a ros node handle
    
        // referece frame
        std::string ref_frame = "map"; // or use "base_link" for targets in the frame relative to the robots position
        // declare an array of PointStamped messages to keep track of the waypoints
        std::vector<geometry_msgs::PointStamped> waypoints;
        // declare 'goal' to use it to keep each waipoints coordinates (double)
        move_base_msgs::MoveBaseGoal goal;
        uint8_t task = 0;
        // parse waypoints from YAML file
        bool built = buildWaypointsFromFile(waypoints);
        if ( !built )
        {
          ROS_FATAL( "building waypoints from a file failed" );
        }
    
      ros::Rate rate(1); // in Hz, makes a best effort at maintaining a particular rate for a loop
        while(this->active)
        {
        switch (task)
                 {
                 case 0:
                   mutex.lock();
                   ROS_INFO("Moving to pick up place");
                   bun(ref_frame, goal, waypoints, 0);
                   task = 1;
                   mutex.unlock();
                   break;
    
                 case 1:
                   mutex.lock();
                   if(!this->Stop){
                     bun(ref_frame, goal, waypoints, 0);
                     Stop = true;
                   }
                   ROS_INFO("Loading of goods ... (waiting 5 seconds)");
                   ros::Duration(5).sleep();
                   ROS_INFO("Moving to drop off zone");
                   // funtion call to run waypoint navigation to waypoint 1
                   bun(ref_frame, goal, waypoints, this->i);
                   ros::Duration(5).sleep();
                   task = 2;
                   mutex.unlock();
                   break;
    
    
                 case 2:
                   if(!this->Stop){
                   bun(ref_frame, goal, waypoints, this->i);
                   Stop = true;
                   }
                   ROS_INFO_ONCE("Click on OTP Button");
                   this->active = false;
                   break;
    
                 }
      }
        ROS_INFO_ONCE("Emitting");
        emit over();
        QThread::quit();
    //}
    }
    

    loading_area.h

    #pragma once
    
    #include "navthread.h"
    
    namespace Ui {
    class Loading_area;
    }
    
    class Loading_area : public QWidget
    {
      Q_OBJECT
    
    public:
      explicit Loading_area(QWidget *parent = nullptr);
      ~Loading_area();
      NavThread *nav;
      ros::NodeHandle ros_nh;
    
    
    public slots:
      void on_go_clicked();
    
    private slots:
    
      void onfinishing();
    
    private:
      Ui::Loading_area *ui;
      NavThread change;
    
    };
    

    loading_area.cpp

    #include "loading_area.h"
    #include "ui_loading_area.h"
    
    Loading_area::Loading_area(QWidget *parent) :
      QWidget(parent),
      ui(new Ui::Loading_area)
    {
      ui->setupUi(this);
      connect(&change, SIGNAL(over()), this, SLOT(onfinishing()));
      nav = new NavThread(this);
    }
    
    Loading_area::~Loading_area()
    {
      delete ui;
    }
    
    void Loading_area::on_go_clicked()
    {
        QString input = ui->lineEdit->text();
    
        nav->active = true;
        nav->start();
    //    nav->wait();
        while(nav->isFinished())
        {
        ui->stackedWidget->setCurrentIndex(2);
        }
    }
    
    void Loading_area::onfinishing()
    {
      ui->stackedWidget->setCurrentIndex(2);
    }
    
    
    

    Ignore unnecessary code....what I am doing is I am starting the navthread from my on_go_clicked slot in my loading_area.cpp file. In my navthread file I have all the code for robot navigation......what I want to do is when my robot reaces it's final destination I want to change my screen on my QT gui basically when my navthread finishes I want change my GUI screen. I tried calling nav->isFinished() (nav is defined from navthread you can see it in loading_area header file) in my Loading_area::on_go_clicked() slot but it didn't work (as you can see).....I also used

    nav->wait() //(which is commented)
    ui->stackedWidget->setCurrentIndex(2);
    

    this time it worked and screen did got changed after bot reached the goal but I couldn't click anything (application freezed) on my gui application until this thread fininshed working. Is there a way I can change my screen as soon as this thread finishes working but also while thread runs I can click buttons and stuff on my gui application.

    JonBJ 2 Replies Last reply
    0
    • R RoBlox

      these are my files:
      navthread.h

      #pragma once
      
      #include <QObject>
      #include <QThread>
      #include <QtCore>
      
      class NavThread : public QThread
      {
        Q_OBJECT
      public:
        explicit NavThread(QObject *parent = 0);
        bool Stop;
        void run();
        bool active;
        int i;
      
      signals:
        void over();
      
      public slots:
      
      private:
        QMutex mutex;
      
      };
      

      navthread.cpp

      
      
      void NavThread::run()
      {
          ros::NodeHandle ros_nh; // Start the roscpp node by creating a ros node handle
      
          // referece frame
          std::string ref_frame = "map"; // or use "base_link" for targets in the frame relative to the robots position
          // declare an array of PointStamped messages to keep track of the waypoints
          std::vector<geometry_msgs::PointStamped> waypoints;
          // declare 'goal' to use it to keep each waipoints coordinates (double)
          move_base_msgs::MoveBaseGoal goal;
          uint8_t task = 0;
          // parse waypoints from YAML file
          bool built = buildWaypointsFromFile(waypoints);
          if ( !built )
          {
            ROS_FATAL( "building waypoints from a file failed" );
          }
      
        ros::Rate rate(1); // in Hz, makes a best effort at maintaining a particular rate for a loop
          while(this->active)
          {
          switch (task)
                   {
                   case 0:
                     mutex.lock();
                     ROS_INFO("Moving to pick up place");
                     bun(ref_frame, goal, waypoints, 0);
                     task = 1;
                     mutex.unlock();
                     break;
      
                   case 1:
                     mutex.lock();
                     if(!this->Stop){
                       bun(ref_frame, goal, waypoints, 0);
                       Stop = true;
                     }
                     ROS_INFO("Loading of goods ... (waiting 5 seconds)");
                     ros::Duration(5).sleep();
                     ROS_INFO("Moving to drop off zone");
                     // funtion call to run waypoint navigation to waypoint 1
                     bun(ref_frame, goal, waypoints, this->i);
                     ros::Duration(5).sleep();
                     task = 2;
                     mutex.unlock();
                     break;
      
      
                   case 2:
                     if(!this->Stop){
                     bun(ref_frame, goal, waypoints, this->i);
                     Stop = true;
                     }
                     ROS_INFO_ONCE("Click on OTP Button");
                     this->active = false;
                     break;
      
                   }
        }
          ROS_INFO_ONCE("Emitting");
          emit over();
          QThread::quit();
      //}
      }
      

      loading_area.h

      #pragma once
      
      #include "navthread.h"
      
      namespace Ui {
      class Loading_area;
      }
      
      class Loading_area : public QWidget
      {
        Q_OBJECT
      
      public:
        explicit Loading_area(QWidget *parent = nullptr);
        ~Loading_area();
        NavThread *nav;
        ros::NodeHandle ros_nh;
      
      
      public slots:
        void on_go_clicked();
      
      private slots:
      
        void onfinishing();
      
      private:
        Ui::Loading_area *ui;
        NavThread change;
      
      };
      

      loading_area.cpp

      #include "loading_area.h"
      #include "ui_loading_area.h"
      
      Loading_area::Loading_area(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Loading_area)
      {
        ui->setupUi(this);
        connect(&change, SIGNAL(over()), this, SLOT(onfinishing()));
        nav = new NavThread(this);
      }
      
      Loading_area::~Loading_area()
      {
        delete ui;
      }
      
      void Loading_area::on_go_clicked()
      {
          QString input = ui->lineEdit->text();
      
          nav->active = true;
          nav->start();
      //    nav->wait();
          while(nav->isFinished())
          {
          ui->stackedWidget->setCurrentIndex(2);
          }
      }
      
      void Loading_area::onfinishing()
      {
        ui->stackedWidget->setCurrentIndex(2);
      }
      
      
      

      Ignore unnecessary code....what I am doing is I am starting the navthread from my on_go_clicked slot in my loading_area.cpp file. In my navthread file I have all the code for robot navigation......what I want to do is when my robot reaces it's final destination I want to change my screen on my QT gui basically when my navthread finishes I want change my GUI screen. I tried calling nav->isFinished() (nav is defined from navthread you can see it in loading_area header file) in my Loading_area::on_go_clicked() slot but it didn't work (as you can see).....I also used

      nav->wait() //(which is commented)
      ui->stackedWidget->setCurrentIndex(2);
      

      this time it worked and screen did got changed after bot reached the goal but I couldn't click anything (application freezed) on my gui application until this thread fininshed working. Is there a way I can change my screen as soon as this thread finishes working but also while thread runs I can click buttons and stuff on my gui application.

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

      @RoBlox said in How can I change my screen in my GUI application when a thread stops running.:

      Ignore unnecessary code....

      Very hard. What you are supposed to do is reduce the code to minimal for us to look at, not make us have to try to determine what is relevant and what is not....

          nav->active = true;
          nav->start();
      //    nav->wait();
          while(nav->isFinished())
          {
          ui->stackedWidget->setCurrentIndex(2);
          }
      

      Whatever nav is --- a thread?? --- you need to do no more than nav->start() and then exit this slot. Any "waiting" or "while-looping" will block your GUI. You need a signal to be raised when "nav thread" finishes, then you change current widget when your slot receives that.

      R 1 Reply Last reply
      1
      • JonBJ JonB

        @RoBlox said in How can I change my screen in my GUI application when a thread stops running.:

        Ignore unnecessary code....

        Very hard. What you are supposed to do is reduce the code to minimal for us to look at, not make us have to try to determine what is relevant and what is not....

            nav->active = true;
            nav->start();
        //    nav->wait();
            while(nav->isFinished())
            {
            ui->stackedWidget->setCurrentIndex(2);
            }
        

        Whatever nav is --- a thread?? --- you need to do no more than nav->start() and then exit this slot. Any "waiting" or "while-looping" will block your GUI. You need a signal to be raised when "nav thread" finishes, then you change current widget when your slot receives that.

        R Offline
        R Offline
        RoBlox
        wrote on last edited by
        #3

        @JonB sorry for that I have made the changes to my question......also nav is a pointer pointing towards navthread class which is derived from QThread. I didn't get what you meant can you elaborate a bit please.

        1 Reply Last reply
        0
        • Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @RoBlox said in How can I change my screen in my GUI application when a thread stops running.:

          I didn't get what you meant can you elaborate a bit please.

          Don't call

          while(nav->isFinished())
          {
          ui->stackedWidget->setCurrentIndex(2);
          }
          

          But use signals and sots to not block the main event loop.

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

          R 1 Reply Last reply
          0
          • Christian EhrlicherC Christian Ehrlicher

            @RoBlox said in How can I change my screen in my GUI application when a thread stops running.:

            I didn't get what you meant can you elaborate a bit please.

            Don't call

            while(nav->isFinished())
            {
            ui->stackedWidget->setCurrentIndex(2);
            }
            

            But use signals and sots to not block the main event loop.

            R Offline
            R Offline
            RoBlox
            wrote on last edited by
            #5

            @Christian-Ehrlicher I also tried that above you can see that my NavThread::run() function emits a signal over which I have connected to the void Loading_area::onfinishing() slot in my loading_area.cpp file......if that's what you meant it's not working....idk what's wrong there

            1 Reply Last reply
            0
            • R RoBlox

              these are my files:
              navthread.h

              #pragma once
              
              #include <QObject>
              #include <QThread>
              #include <QtCore>
              
              class NavThread : public QThread
              {
                Q_OBJECT
              public:
                explicit NavThread(QObject *parent = 0);
                bool Stop;
                void run();
                bool active;
                int i;
              
              signals:
                void over();
              
              public slots:
              
              private:
                QMutex mutex;
              
              };
              

              navthread.cpp

              
              
              void NavThread::run()
              {
                  ros::NodeHandle ros_nh; // Start the roscpp node by creating a ros node handle
              
                  // referece frame
                  std::string ref_frame = "map"; // or use "base_link" for targets in the frame relative to the robots position
                  // declare an array of PointStamped messages to keep track of the waypoints
                  std::vector<geometry_msgs::PointStamped> waypoints;
                  // declare 'goal' to use it to keep each waipoints coordinates (double)
                  move_base_msgs::MoveBaseGoal goal;
                  uint8_t task = 0;
                  // parse waypoints from YAML file
                  bool built = buildWaypointsFromFile(waypoints);
                  if ( !built )
                  {
                    ROS_FATAL( "building waypoints from a file failed" );
                  }
              
                ros::Rate rate(1); // in Hz, makes a best effort at maintaining a particular rate for a loop
                  while(this->active)
                  {
                  switch (task)
                           {
                           case 0:
                             mutex.lock();
                             ROS_INFO("Moving to pick up place");
                             bun(ref_frame, goal, waypoints, 0);
                             task = 1;
                             mutex.unlock();
                             break;
              
                           case 1:
                             mutex.lock();
                             if(!this->Stop){
                               bun(ref_frame, goal, waypoints, 0);
                               Stop = true;
                             }
                             ROS_INFO("Loading of goods ... (waiting 5 seconds)");
                             ros::Duration(5).sleep();
                             ROS_INFO("Moving to drop off zone");
                             // funtion call to run waypoint navigation to waypoint 1
                             bun(ref_frame, goal, waypoints, this->i);
                             ros::Duration(5).sleep();
                             task = 2;
                             mutex.unlock();
                             break;
              
              
                           case 2:
                             if(!this->Stop){
                             bun(ref_frame, goal, waypoints, this->i);
                             Stop = true;
                             }
                             ROS_INFO_ONCE("Click on OTP Button");
                             this->active = false;
                             break;
              
                           }
                }
                  ROS_INFO_ONCE("Emitting");
                  emit over();
                  QThread::quit();
              //}
              }
              

              loading_area.h

              #pragma once
              
              #include "navthread.h"
              
              namespace Ui {
              class Loading_area;
              }
              
              class Loading_area : public QWidget
              {
                Q_OBJECT
              
              public:
                explicit Loading_area(QWidget *parent = nullptr);
                ~Loading_area();
                NavThread *nav;
                ros::NodeHandle ros_nh;
              
              
              public slots:
                void on_go_clicked();
              
              private slots:
              
                void onfinishing();
              
              private:
                Ui::Loading_area *ui;
                NavThread change;
              
              };
              

              loading_area.cpp

              #include "loading_area.h"
              #include "ui_loading_area.h"
              
              Loading_area::Loading_area(QWidget *parent) :
                QWidget(parent),
                ui(new Ui::Loading_area)
              {
                ui->setupUi(this);
                connect(&change, SIGNAL(over()), this, SLOT(onfinishing()));
                nav = new NavThread(this);
              }
              
              Loading_area::~Loading_area()
              {
                delete ui;
              }
              
              void Loading_area::on_go_clicked()
              {
                  QString input = ui->lineEdit->text();
              
                  nav->active = true;
                  nav->start();
              //    nav->wait();
                  while(nav->isFinished())
                  {
                  ui->stackedWidget->setCurrentIndex(2);
                  }
              }
              
              void Loading_area::onfinishing()
              {
                ui->stackedWidget->setCurrentIndex(2);
              }
              
              
              

              Ignore unnecessary code....what I am doing is I am starting the navthread from my on_go_clicked slot in my loading_area.cpp file. In my navthread file I have all the code for robot navigation......what I want to do is when my robot reaces it's final destination I want to change my screen on my QT gui basically when my navthread finishes I want change my GUI screen. I tried calling nav->isFinished() (nav is defined from navthread you can see it in loading_area header file) in my Loading_area::on_go_clicked() slot but it didn't work (as you can see).....I also used

              nav->wait() //(which is commented)
              ui->stackedWidget->setCurrentIndex(2);
              

              this time it worked and screen did got changed after bot reached the goal but I couldn't click anything (application freezed) on my gui application until this thread fininshed working. Is there a way I can change my screen as soon as this thread finishes working but also while thread runs I can click buttons and stuff on my gui application.

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

              @RoBlox
              ... and if it still doesn't work after getting rid of the while loop, put a qDebug() into onfinishing() to make sure it's being hit....

              You could also put suitable breakpoints into a debugger to examine behaviour.

              R 2 Replies Last reply
              0
              • JonBJ JonB

                @RoBlox
                ... and if it still doesn't work after getting rid of the while loop, put a qDebug() into onfinishing() to make sure it's being hit....

                You could also put suitable breakpoints into a debugger to examine behaviour.

                R Offline
                R Offline
                RoBlox
                wrote on last edited by
                #7

                @JonB my code does exit out of while loop I have put a print statement to check that above my emit command in NavThread.cpp run() function

                1 Reply Last reply
                0
                • JonBJ JonB

                  @RoBlox
                  ... and if it still doesn't work after getting rid of the while loop, put a qDebug() into onfinishing() to make sure it's being hit....

                  You could also put suitable breakpoints into a debugger to examine behaviour.

                  R Offline
                  R Offline
                  RoBlox
                  wrote on last edited by
                  #8

                  @JonB but apparently my slot is not receiving the signal....idk why
                  I checked it by adding qDebug to it.

                  1 Reply Last reply
                  0
                  • Christian EhrlicherC Offline
                    Christian EhrlicherC Offline
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @RoBlox said in How can I change my screen in my GUI application when a thread stops running.:

                    connect(&change, SIGNAL(over()), this, SLOT(onfinishing()));

                    This is wrong... at least it's not the thread you're starting below. You've two NavThread objects in your Loading_area (one object and one pointer) - fix your code.

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

                    R 1 Reply Last reply
                    3
                    • Christian EhrlicherC Christian Ehrlicher

                      @RoBlox said in How can I change my screen in my GUI application when a thread stops running.:

                      connect(&change, SIGNAL(over()), this, SLOT(onfinishing()));

                      This is wrong... at least it's not the thread you're starting below. You've two NavThread objects in your Loading_area (one object and one pointer) - fix your code.

                      R Offline
                      R Offline
                      RoBlox
                      wrote on last edited by
                      #10

                      @Christian-Ehrlicher Ohhh my bad.....Thanks :)

                      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