How can I change my screen in my GUI application when a thread stops running.
-
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_clickedslot 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 callingnav->isFinished()(nav is defined from navthread you can see it in loading_area header file) in myLoading_area::on_go_clicked()slot but it didn't work (as you can see).....I also usednav->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.
-
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_clickedslot 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 callingnav->isFinished()(nav is defined from navthread you can see it in loading_area header file) in myLoading_area::on_go_clicked()slot but it didn't work (as you can see).....I also usednav->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.
@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
navis --- a thread?? --- you need to do no more thannav->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. -
@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
navis --- a thread?? --- you need to do no more thannav->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. -
@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.
-
@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.
@Christian-Ehrlicher I also tried that above you can see that my
NavThread::run()function emits a signal over which I have connected to thevoid 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 -
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_clickedslot 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 callingnav->isFinished()(nav is defined from navthread you can see it in loading_area header file) in myLoading_area::on_go_clicked()slot but it didn't work (as you can see).....I also usednav->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.
-
@RoBlox
... and if it still doesn't work after getting rid of thewhileloop, put aqDebug()intoonfinishing()to make sure it's being hit....You could also put suitable breakpoints into a debugger to examine behaviour.
-
@RoBlox
... and if it still doesn't work after getting rid of thewhileloop, put aqDebug()intoonfinishing()to make sure it's being hit....You could also put suitable breakpoints into a debugger to examine behaviour.
-
@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.
-
@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.
@Christian-Ehrlicher Ohhh my bad.....Thanks :)