I'm new to threading and doing an exercise question where I'm writing a program that creates a list of files in a directory and displays it in a QTableWidget. It uses a separate thread to do the file finding. I'm not sub-classing from QThread due to this question. When I run the program and search a directory it works fine the first time and displays the names of the files in the table view as expected. But when I try do it again the QTableView doesn't update.
While debugging I notice my breakpoints in my fileFinder class don't get triggered on the second try. It seems like the thread doesn't run again the second time like it does the first and I can't figure out why. I'm pretty sure it's a simple bug that I'm missing. Any help will be apprecaited. The code:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "filefinder.h"
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void addToTable(QString name);
void on_btnBrowse_clicked();
private:
Ui::MainWindow *ui;
QThread workerThread;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//set up tableWidget code here omitted
}
void MainWindow::on_btnBrowse_clicked()
{
//clear tableWidget contents
ui->tableFiles->setRowCount(0);
fileFinder *finder = new fileFinder;
finder->moveToThread(&workerThread);
connect(&workerThread, SIGNAL(started()), finder, SLOT(run())); //execute run() function when worker thread has started
connect(finder, SIGNAL(name(QString)), this, SLOT(addToTable(QString))); //pass names from thread to handler slot
connect(&workerThread, SIGNAL(finished()), finder, SLOT(deleteLater())); //delete thread when done
//get directory
QString dir = QFileDialog::getExistingDirectory(this, "Select Directory", "/home", QFileDialog::ShowDirsOnly);
ui->dirEdit->setText(dir);
//set directory in thread object
finder->setDir(dir);
//start worker thread
workerThread.start();
}
//add each name to tableWidget one at a time
void MainWindow::addToTable(QString name)
{
QTableWidgetItem *fileName = new QTableWidgetItem(name);
int row = ui->tableFiles->rowCount();
ui->tableFiles->insertRow(row);
ui->tableFiles->setItem(row, 0, fileName);
}
MainWindow::~MainWindow()
{
workerThread.quit();
workerThread.wait();
delete ui;
}
filefinder.h
#ifndef FILEFINDER_H
#define FILEFINDER_H
#include <QStringList>
#include <QThread>
class fileFinder : public QObject
{
Q_OBJECT
public:
fileFinder();
void searchDir();
void setDir(QString path);
public slots:
void run();
signals:
void name(QString n);
private:
QStringList files;
QString m_dir;
};
#endif // FILEFINDER_H
filefinder.cpp
#include "filefinder.h"
#include <unistd.h>
#include <QDir>
fileFinder::fileFinder()
{
}
//return list of all files in the directory
void fileFinder::searchDir()
{
QDir dir;
dir.setPath(m_dir);
//get list of file names sorted by name
files = dir.entryList(QDir::Files, QDir::Name);
}
//set the selected directory
void fileFinder::setDir(QString path)
{
m_dir = path;
}
//executed when thread is started
void fileFinder::run()
{
searchDir();
//iterate through list of files and emit names one by one
foreach(QString f, files){
emit(name(f));
usleep(100); //pause inbetween emits
}
}
This line will destroy your thread object after finish
connect(&workerThread, SIGNAL(finished()), finder, SLOT(deleteLater()));
You need to keep your thread as pointer and recreate it before start.
In mainwindow.h
QThread* workerThread;
And then
workerThread = new QThread;
finder->moveToThread(workerThread);
connect(workerThread, SIGNAL(started()), finder, SLOT(run()));
connect(finder, SIGNAL(name(QString)), this, SLOT(addToTable(QString)));
connect(workerThread, SIGNAL(finished()), finder, SLOT(deleteLater()));
Do 2 changes:
Change the type of workerThread to QThread*
assign every btn_Browse_clicked() a new QThread() to workerThread
I'm sorry, I don't know why it works, but it does.
Maybe anybody else knows an answer, i would be interested in.
Related
Hello Im trying to print my result from a thread to textBrower in qtwidget QT but I cant, either I get error or the program wont compile
is there another way ?? how can I change the textBrowser outside of the class's function??
PS BTW I need to keep looping inside the thread cuz actually im getting some data from uart in final program (in this code i just wanna print "lol" which eventually I wanna change it with some other code which take data ) so I cant come out of the loop
eventually i want use some process from another library and show the resault REAL TIME
bool stop;
out::out(QWidget *parent) :
QWidget(parent),
ui(new Ui::out)
{
ui->setupUi(this);
ui->textBrowser->setText("lol");
}
out::~out()
{
delete ui;
}
///////////////////////////////////////////////
class t : public out, public QThread
{
public:
void run()
{
while(1){
qDebug()<<"hi"<<i;
// ui->textBrowser->setText("lol"); I tried to use this but it didnt worked
if(stop==true){
QThread::exec();
}
}
}
};
void mamad1(void){ //this function get called from another cpp file and its for starting the thread
stop=false;
t *b = new t;
b->start();
}
void out::on_pushButton_clicked() // a push button to stop the thread
{
stop=true;
}
I tried make ui in out.h file a public property and use ui->textBrowser->setText("lol"); but it didn't worked the program freezed and i got this
error : (Parent is QTextDocument(0x208d812a510), parent's thread is QThread(0x208d6816de0), current thread is QThread(0x208dac94e10)
I tried to use connect() also and didn't worked or I didn't use it right
The concept of QT the GUI thread is called the master thread. This thread has an event queue. In general, this event queue is populated by internal and external events. Moreover, the queue between threads is an efficient approach for thread communication. The same is true for the worker threads as well. When you call the start method through the worker threads their signal queue is created and ready to be consumed by the corresponding thread.
Let's come back to your question. The solution is simple. From your worker threads, you can just send a signal to the master thread. The master thread will see this event that modifies the GUI item and forwards this signal/event to the slot that is responsible to take action accordingly. Just define a signal in your worker thread and connect your master thread to this signal with a given slot.
UPDATE FOR SOLUTION
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <MyWorkerThread.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void setWorkerThread(MyWorkerThread* thread);
void connectToSignals();
public slots:
void handleTextBoxSignal(const QString& text);
private:
Ui::MainWindow *ui;
MyWorkerThread* m_worker_thread{nullptr};
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::setWorkerThread(MyWorkerThread* thread)
{
m_worker_thread = thread;
}
void MainWindow::connectToSignals()
{
QObject::connect(m_worker_thread,
SIGNAL(changeTextOnUI(QString)),
this,
SLOT(handleTextBoxSignal(QString)));
}
void MainWindow::handleTextBoxSignal(const QString& text)
{
qDebug() << "Text box change signal received with text: " << text;
auto text_box = findChild<QTextEdit*>("myTxtEdit");
if(text_box != nullptr)
{
text_box->setText(text);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
MyWorkerThread.h
#ifndef MYWORKERTHREAD_H
#define MYWORKERTHREAD_H
#include <QObject>
#include <QThread>
class MyWorkerThread : public QThread
{
Q_OBJECT
public:
MyWorkerThread(QObject* parent = nullptr);
void stopThread();
signals:
void changeTextOnUI(const QString& text);
private:
void run() override;
bool m_exit{false};
};
#endif // MYWORKERTHREAD_H
MyWorkerThread.cpp
#ifndef MYWORKERTHREAD_H
#define MYWORKERTHREAD_H
#include <QObject>
#include <QThread>
class MyWorkerThread : public QThread
{
Q_OBJECT
public:
MyWorkerThread(QObject* parent = nullptr);
void stopThread();
signals:
void changeTextOnUI(const QString& text);
private:
void run() override;
bool m_exit{false};
};
#endif // MYWORKERTHREAD_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
MyWorkerThread* worker_thread = new MyWorkerThread();
w.setWorkerThread(worker_thread);
w.connectToSignals();
worker_thread->start();
w.show();
return a.exec();
}
In the above code, you see the full solution to your problem. In the worker thread, we increment a static counter and concatenate it with a string and send it to the master thread that manages the UI elements. We emit a signal and this signal is landed on the slot. This way the master thread updates the text box on the screen per 5 seconds. The worker thread sleeps for 5 seconds at each iteration.
How can I run loop functions in different QThreads? I need to run in different threads because if I don't do it, the loops break.
How to make the on_pushTurnOn_clicked be executed in other thread, and the loop that pushTurnOn must be able to be canceled by on_pushTurnOff_clicked even on a different thread.
MainWindow .h code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QThread> //I don't know how to use it
#include <QTimer>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushTurnOn_clicked();
void on_pushTurnOff_clicked();
private:
QTimer *timerLoop;
};
#endif // MAINWINDOW_H
MainWindow cpp code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushTurnOn_clicked()
{
timerLoop = new QTimer(this);
timerLoop->setInterval(3000);
timerLoop->setSingleShot(true);
connect(timerLoop, SIGNAL(timeout()),
SLOT(on_pushTurnOn_clicked()));
qDebug()<<"the loop was started";
timerLoop->start(); //start the loop
}
void MainWindow::on_pushTurnOff_clicked()
{
qDebug()<<"the loop was stoped";
timerLoop->stop(); //stop the loop
}
I will start with a side note. Your memory allocation for timerLoop in on_pushTurnOn_clicked() will cause a memory leak due to absence of deallocation, even though it is a single shot timer. You are creating a new QTimer without destroying the previous allocated one. The better approach is to just allocate memory once in the constructor and just start the timer in on_pushTurnOn_clicked().
Coming back to your question, you will have to split your class into two, one is your mainWindow which has the slots for on_pushTurnOn_clicked() and on_pushTurnOff_clicked(), other possible UI elements and non-intensive tasks.
The second class is a worker which contains the QTimer along with the actual work load. So you would essentially have something like this:
MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
//constructor
ui->setupUi(this);
this->worker = new Worker(); //object of WorkerClass type
QThread *thread = new QThread();
worker->moveToThread(thread);
connect(this, SIGNAL(startOrStopTimerSignal(bool), worker, SLOT(startStopTimer(bool));
}
void MainWindow::on_pushTurnOn_clicked()
{
if(Busy==1){
qDebug()<<"Is busy!";
}
if(Busy==0){
FuncaoLoop(RandomParameter1, RandomParameter2);
}
//start the timer through a signal (timers need to be started in their own threads)
emit startOrStopTimerSignal(true);
}
void MainWindow::on_pushTurnOff_clicked()
{
emit startOrStopTimerSignal(false); //stop the timer
}
WorkerClass.h/.cpp:
WorkerClass::WorkerClass(QObject *parent) : QObject(parent)
{
timerLoop= new QTimer(this);
connect(timerLoop, SIGNAL(timeout()), this, SLOT(workLoad())); //timer connect to your actual task
}
void WorkerClass::startStopTimer(bool start)
{
if (start)
timerLoop->start();
else
timerLoop->stop();
}
WorkerClass::workLoad()
{
//whatever task for your PLC
}
Hope this helps you out.
I applied an C++ example of working with threads in Qt 5.7. All things are good except two things:
1- I used Signal & Slot to update my label in the main form. the problem is that is no effect. Really, I don't know where is the issue.
2- The loop works fine, but when I exit my program I see (throught the "Application Output") that the loop still work (I think that's related with the started thread).
This my little example:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void updateLabelText(const QString TheString);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
//#include <QDebug>
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QThread *workerThread = new QThread;
Worker *worker = new Worker;
worker->moveToThread(workerThread);
connect(worker, SIGNAL(sendText(const QString)), this, SLOT(updateLabelText(QString)));
workerThread->start();
}
void MainWindow::updateLabelText(const QString TheString)
{
ui->label->setText(TheString);
}
worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker();
public slots:
void doWork();
signals:
void sendText(const QString);
};
#endif // WORKER_H
worker.cpp
#include "worker.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QThread>
#include <QMessageBox>
#include <QApplication>
Worker::Worker()
{
doWork();
}
void Worker::doWork()
{
for (int i = 0; i<999999; i++) {
emit sendText(QString::number(i));
qDebug() << "The number is : " + QString::number(i);
qApp->processEvents();
//QThread::msleep(5);
}
}
How can I fix this?
Thanks.
In your code, doWork() function is called from the Worker's constructor, the constructor is invoked in the main thread (that is done in the line Worker* worker= new Worker;).
Of course, that is not what you meant to do, since it will cause the main thread to execute the for loop in doWork() before even reaching into the connect call.
Instead of calling doWork() from the Worker's constructor, you should connect the thread's started() signal to doWork() slot, then call thread->start() after moving the Worker object to the new thread. This will leverage Qt cross-thread signals to invoke doWork() in the new thread as soon as it starts.
Here is how your code should look like:
#include <QtWidgets>
//QThread wrapper for safe destruction
//see http://stackoverflow.com/a/19666329
class Thread : public QThread{
using QThread::run; //final
public:
Thread(QObject* parent= nullptr): QThread(parent){}
~Thread(){ quit(); wait();}
};
class Worker : public QObject{
Q_OBJECT
public:
explicit Worker(QObject* parent= nullptr): QObject(parent){}
~Worker()= default;
Q_SIGNAL void sendText(QString text);
Q_SIGNAL void workFinished();
Q_SLOT void doWork(){
for (int i = 0; i<1000; i++) {
emit sendText(QString::number(i));
QThread::msleep(5);
}
emit workFinished();
}
};
class Widget : public QWidget{
Q_OBJECT
public:
explicit Widget(QWidget* parent= nullptr): QWidget(parent){
layout.addWidget(&buttonWork);
layout.addWidget(&label);
connect(&buttonWork, &QPushButton::clicked,
this, &Widget::buttonWorkClicked);
}
~Widget()= default;
Q_SLOT void buttonWorkClicked(){
Thread* thread= new Thread(this);
Worker* worker= new Worker;
worker->moveToThread(thread);
//invoke doWork as soon as the thread is started
connect(thread, &QThread::started, worker, &Worker::doWork);
connect(worker, &Worker::sendText, this, &Widget::updateLabelText);
//quit the thread when work is finished
connect(worker, &Worker::workFinished, thread, &QThread::quit);
//destroy thread and worker object when work is finished
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
connect(thread, &QThread::finished, worker, &QObject::deleteLater);
//start the thread
thread->start();
}
Q_SLOT void updateLabelText(QString text){
label.setText(text);
}
private:
QVBoxLayout layout{this};
QPushButton buttonWork{"Work"};
QLabel label{"No work yet"};
};
int main(int argc, char* argv[]){
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
I solved my problem by following the comment of Mr #Mike.
Simply, I removed the doWork() function from the instructor. Then, I added new connection between the thread's started() SIGNAL and worker's doWork() SLOT.
So thes are the changes:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QThread *workerThread = new QThread;
Worker *worker = new Worker;
connect(workerThread, SIGNAL(started()), worker, SLOT(doWork()),Qt::QueuedConnection);
connect(worker, SIGNAL(sendText(const QString)), this, SLOT(updateLabelText(const QString)),Qt::QueuedConnection);
worker->moveToThread(workerThread);
workerThread->start();
}
void MainWindow::updateLabelText(const QString TheString)
{
ui->label->setText(TheString);
}
worker.cpp
#include "worker.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QThread>
#include <QMessageBox>
#include <QApplication>
Worker::Worker()
{
doWork();
}
void Worker::doWork()
{
for (int i = 0; i<999999; i++) {
emit sendText(QString::number(i));
qDebug() << "The number is : " + QString::number(i);
qApp->processEvents();
QThread::msleep(5);
}
}
I have seen a similar question, but I feel that I am implementing the correct pattern and still I can't get it done!
Well, I have a Gui to start and stop data acquisition from a serial port and display necessary communication messages. To keep the Gui responsive, I move the worker to a thread. I tried to implement thread affinity, according to: How to Use QThread in the Right Way and How To Really, Truly Use QThreads. When I click on start button, I receive;
QWinEventNotifier: event notifiers cannot be enabled from another thread
QWinEventNotifier: event notifiers cannot be enabled from another thread
QWinEventNotifier: event notifiers cannot be enabled from another thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0x142cd390), parent's thread is QThread(0x1259b070), current thread is QThread(0x142db1f0)
What am I missing? Here is a part of the code related to my question:
Worker header
#ifndef COMPORT_H
#define COMPORT_H
#include <QObject>
#include <QDebug>
#include <QSerialPort>
class QTimer;
class ComPort : public QObject
{
Q_OBJECT
public:
explicit ComPort(const QString &portName, QObject* parent = 0);
~ComPort();
private:
QSerialPort* port;
QString portMsg;
QByteArray responseData;
signals:
void finished();
private slots:
void onReadyRead();
void setupPort();
};
#endif // COMPORT_H
Worker cpp
#include "comport.h"
ComPort::ComPort(const QString &portName, QObject *parent)
:QObject(parent)
{
this->port = new QSerialPort(portName);
}
ComPort::~ComPort()
{
port->close();
delete port;
}
void ComPort::setupPort()
{
port->setBaudRate(QSerialPort::Baud19200);
port->setDataBits(QSerialPort::Data8);
port->setFlowControl(QSerialPort::NoFlowControl);
port->setParity(QSerialPort::NoParity);
port->setStopBits(QSerialPort::OneStop);
connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
*SOME CODE HERE*
}
void ComPort::onReadyRead()
{
QByteArray bytes = port->readAll() ;
qDebug() << "bytes:" << bytes <<"\n";
responseData.append(bytes);
}
and Gui
#include "gui.h"
#include "ui_gui.h"
gui::gui(QWidget *parent) :
QDialog(parent),
ui(new Ui::gui)
{
ui->setupUi(this);
connect(ui->startButton, SIGNAL(clicked()), this, SLOT(OnstartButtonClicked()));
}
gui::~gui()
{
delete ui;
}
void gui::OnstartButtonClicked()
{
QThread* cThread = new QThread;
ComPort* cPort = new ComPort(QString("COM4"));
cPort->moveToThread(cThread);
connect(cPort, SIGNAL(finished()), cThread, SLOT(quit()));
connect(cPort, SIGNAL(finished()), cPort, SLOT(deleteLater()));
connect(cThread, SIGNAL(finished()), cThread, SLOT(deleteLater()));
connect(cThread, SIGNAL(started()), cPort, SLOT(setupPort()));
cThread->start();
}
Thank to the answer from Kim Bowles Sørhus, I solved my problem. I was creating a serial port in the constructor of ComPort that is called in the main thread. When the cPort object is moved to the cThread the QSerialPort still has its thread affinity set to the original thread. A solution is to create the QSerialPort in ComPort::setupPort.
My mainwindow have a side GUI with a QGraphicsView in the center, there is a logic class which make different calculations which triggered by the GUI and effects the QGraphicsView.
Some of the calculations are heavy which make the GUI go to sleep, there is a QProgressBar and some other Qt items which provides some data while the calculations are been made, so when the GUI process goes to sleep those items show there updated result only when the process has finished. I understand that it because the logic class and the UI are under the same process,
I was trying to correct this by doing: My old question and Maya's Programming Blog
But I came to understanding that both are not sufficient to my code as I have several methods that run heavy calculations and some of them returning values. Both talking about doing something like this: connect(thread, SIGNAL(started()), worker, SLOT(process()));... than thread->start();, but in my code there is no single main process, so if I want to work in that way, from what I understand I need to create a thread before each process method, move the logic class to this thread and than connect the process method with the thread start method, which not sounds to me as the proper way to do this.
So I ask for a way to fully separate the logic layer from the view layer, so any method which invoked the logic layer will run on a different process (which is the same for all logic class methods), so the view layer won't go to sleep.
Note: there is no problems of synchronicity, when a calculation been made it's the only one which work at a time.
An example of my problem:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "Logic/worker.h"
namespace Ui {
class MainWindow;
#define MAXLOOP 1000000
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
private slots:
void startProcessing1();
void processing1Done();
void on_pushButton_exit_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
/////////////////////////////////////////////////////////////////////////////////
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QThread"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->progressBar_1->setVisible(false);
ui->progressBar_1->setMaximum(MAXLOOP);
ui->progressBar_1->setMinimum(0);
connect(ui->pushButton_1, SIGNAL(clicked()), this, SLOT(startProcessing1()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::startProcessing1()
{
ui->progressBar_1->setVisible(true);
Worker *worker = new Worker(MAXLOOP);
QThread* thread = new QThread;
worker->moveToThread(thread);
connect(worker, SIGNAL(finished1Hide()), this, SLOT(processing1Done()));
connect(worker, SIGNAL(changePbar1(int)), ui->progressBar_1, SLOT(setValue(int)));
connect(thread, SIGNAL(started()), worker, SLOT(process1()));
connect(worker, SIGNAL(finished1()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished1()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
void MainWindow::processing1Done()
{
ui->progressBar_1->setVisible(false);
}
void MainWindow::on_pushButton_exit_clicked()
{
this->close();
}
/////////////////////////////////////////////////////////////////////////////////
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(int maxLoop, QObject *parent = 0);
signals:
void finished1();
void finished1Hide();
void changePbar1(int val);
public slots:
void process1();
private:
int m_maxLoop;
};
#endif // WORKER_H
/////////////////////////////////////////////////////////////////////////////////
#include "worker.h"
Worker::Worker(int maxLoop, QObject *parent) :
QObject(parent)
{
m_maxLoop = maxLoop;
}
void Worker::process1()
{
int sum = 0;
for(int i = 0; i < m_maxLoop; ++i)
{
emit changePbar1(i);
sum += i;
}
emit finished1();
emit finished1Hide();
}