What is the easiest way to play a continuous warning sound that lasts several minutes without affecting the main thread's performance?
I know that QSound can work in asynchronous mode, however, according to here:
Qt: How to play sound witout blocking main thread?
QSound would still bring noticeable affect on the main thread.
Is there any simple solution to this?
As suggested earlier, try to play sound in another thread. But QSound has not enough signals to control it. If you want get deeper control you can use QSoundEffect Try this:
header:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
signals:
public slots:
void process();
};
#endif // WORKER_H
Cpp
#include "worker.h"
#include <QSound>
Worker::Worker(QObject *parent) :
QObject(parent)
{
}
void Worker::process()
{
QSound *sound = new QSound("path");
sound->setLoops(100);
sound->play();
}
Usage:
QThread *thr = new QThread;
Worker * work = new Worker;
connect(thr, SIGNAL(started()), work, SLOT(process()));
work->moveToThread(thr);
thr->start();
To play it several minutes you can set infinite number of loops and use QTimer (maybe singleShot) to end thread and delete object(music will be stopped too).
Related
When my program opens, a connection is made to my server via QNetworkAccessManager::connectToHostEncrypted() which is called in the constructor of MainWindow. This freezes the GUI thread and causes a noticeable delay until the connection is finished. (Sometimes over a full second longer)
This problem is worsened by the fact that my program fades in at startup, so while the GUI thread is blocked, the fade in doesn't start until after the connection is done. In a default Qt project, this is noticeable in other ways like widgets not being painted.
To keep the GUI thread going, I moved QNetworkAccessManager into a completely different thread with QThread thinking this would solve the issue, however the GUI thread still freezes. This makes no sense to me.
Here is a minimally compilable example project.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QThread>
class Connection : public QNetworkAccessManager
{
Q_OBJECT
public:
Connection(QObject *parent) : QNetworkAccessManager(parent){}
public slots:
void openConnection(){
connectToHostEncrypted("https://www.url.com");
}
signals:
void closeThread(bool);
};
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QThread *connectionThread;
Connection *connection;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connection = new Connection(this);
connectionThread = new QThread();
connection->moveToThread(connectionThread);
connect(connectionThread, SIGNAL(started()), connection, SLOT(openConnection()));
connect(connection, SIGNAL(closeThread(bool)), connectionThread, SLOT(quit()));
connect(connectionThread, SIGNAL(finished()), connectionThread, SLOT(deleteLater()));
connectionThread->start();
}
MainWindow::~MainWindow()
{
delete connection;
delete ui;
}
This example project creates an instance of Connection which is a subclass of QNetworkAccessManager that I then move to another thread via moveToThread(). This is how I do all my worker threads.
When the thread's start() signal is emitted, openConnection() calls connectToHostEncrypted() which is where the GUI thread freezes.
I have tried just calling a regular HTTP request instead, however the problem persists since an initial connection still needs to be made.
How come the GUI thread still freezes even though the connection is done in another thread?
The issue was I passed this as a parent to the Connection instance which meant moveToThread() couldn't be completed. I just had to check the output log to see that, but I must have missed it!
By removing that parent, the connection was now in it's own thread.
I further tested this by calling QThread::sleep(3) inside that openConnection() call and there was still no delay.
try to use :
connect(connectionThread, SIGNAL(started()), connection, SLOT(openConnection(),Qt::QueuedConnection);
I created a minimal QT GUI example to update widgets from a worker thread based on the recommended approach in the The QThread 5.12 documentation.
As described in the QThread 5.12 documentation, the Worker class (with a potentially long void doWork(const QString ¶meter) method is:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
and the corresponding Controller class is:
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
Unlike sub-classing from a QThread, the approach shown in the documentation shows the recommended way that uses a controller and a worker that extends QObject rather than extending QThread and overriding the QThread::run method, however it does not show how these should be used in the context of a real example.
I need to use an QT Worker thread that updates widgets on a GUI using a timer.
I also need to be able to halt and restart/relaunch this thread with different parameters and I am having some trouble with how to do this correctly. indicates the preferred way to do this via a Controller and a Worker but the connect logic is a bit confusing.
The place where I need help is how to properly integrate the timer in my worker thread and also how to stop and restart a replacement worker when the current one has either finished or been interrupted and restarted.
My working code is made up of the following files.
Controller.h
#pragma once
// SYSTEM INCLUDES
#include <QObject>
#include <QThread>
// APPLICATION INCLUDES
#include "Worker.h"
// DEFINES
// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STRUCTS
// TYPEDEFS
// FORWARD DECLARATIONS
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller(/*MainWindow* mainWindow*/) {
auto worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &) {
// how do I update the mainWindow from here
}
signals:
void operate(int);
};
Worker.h
#pragma once
// SYSTEM INCLUDES
#include <QTimer>
#include <QObject>
#include <QEventLoop>
// APPLICATION INCLUDES
#include "Worker.h"
// DEFINES
// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STRUCTS
// TYPEDEFS
// FORWARD DECLARATIONS
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(int count) {
QString result = "finished";
// Event loop allocated in workerThread
// (non-main) thread affinity (as moveToThread)
// this is important as otherwise it would occur
// on the main thread.
QEventLoop loop;
for (auto i=0; i< count; i++) {
// wait 1000 ms doing nothing...
QTimer::singleShot(1000, &loop, SLOT(quit()));
// process any signals emitted above
loop.exec();
emit progressUpdate(i);
}
emit resultReady(result);
}
signals:
void progressUpdate(int secondsLeft);
void resultReady(const QString &result);
};
MainWindow.h - I needed to add a Controller member here. I also added an updateValue slot here where I wish to update the GUI. Unfortunately I don't know how to get the controller or the worker to connect a signal from the thread to update this slot.
#pragma once
// SYSTEM INCLUDES
#include <memory>
#include <QMainWindow>
// APPLICATION INCLUDES
// DEFINES
// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STRUCTS
// TYPEDEFS
// FORWARD DECLARATIONS
namespace Ui {
class MainWindow;
}
class Controller;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void updateValue(int secsLeft);
private:
Ui::MainWindow *ui;
std::unique_ptr<Controller> mpController;
};
MainWindow.cpp -
#include <QThread>
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "Controller.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, mpController(std::make_unique<Controller>())
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
emit mpController->operate(100);
}
void MainWindow::updateValue(int secsLeft)
{
ui->secondsLeft->setText(QString::number(secsLeft));
}
and finally main.cpp
#include "MainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
I basically need help and an explanation on how I should use the QT Thread's controller/worker integrated in my GUI.
I'll try to answer all the issues you're addressing in your question:
I don't know how to get the controller or the worker to connect a signal from the thread to update this slot.
You got that almost right yourself.
Your Worker lives within the event loop of your Controller:
+--GUI-thread--+ (main event loop)
| MainWindow, |
| Controller --o-----> +--QThread--+ (own event loop in ::exec())
+--------------+ | Worker |
+-----------+
Communication between Controller and Worker must happen through signal-slot-connections. In between MainWindow and Controller signals help keep dependencies to a minimum.
You can imagine Controller as a kind of relay: Commands from MainWindow get forwarded through Controller to the Worker. Results from Worker get forwarded through the Controller to anyone who is interested.
For this, you can simply define signals in Controller:
class Controller : public QObject
{
//...
signals:
void SignalForwardResult(int result);
};
and then instead of
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
use the new signal:
connect(worker, &Worker::resultReady, this, &Controller::SignalForwardResult);
// Yes, you can connect a signal to another signal the same way you would connect to a slot.
and in your MainWindow constructor:
//...
ui->setupUi(this);
connect(mpController, &Controller::SignalForwardResult, this, &MainWindow::displayResult);
Likewise for Worker::progressUpdate() -> Controller::SignalForwardProgress() -> MainWindow::updateValue().
how to stop and restart a replacement worker when the current one has either finished or been interrupted and restarted.
Either create a new worker for each task or use a persistent worker that can react on new task requests.
You start a task by sending it to the worker ::doWork() function.
A task ends by itself when the long work is finished. You get a notification via the worker's resultReady signal.
Cancelling a task is only possible by intervention
If you indeed have a QTimer, you can use a cancel() slot because that will be invoked in the thread's event loop before the next timeout.
If you have a long-running calculation, you need to share some token that you read from inside your calculation method and set from your GUI thread. I usually use a shared QAtomicInt pointer for that, but a shared bool usually suffices too.
Note that while a method is running on a thread, that thread's event loop is blocked and won't receive any signals until the method is finished.
DON'T use QCoreApplication::processEvents() except if you really know, what you're doing. (And expect that you don't!)
how to properly integrate the timer in my worker thread
You shouldn't.
I guess you use a background thread because there is so much work to do or you need to blocking wait for so long that it would block the GUI, right? (If not, consider not using threads, saves you a lot of headaches.)
If you need a timer, make it a member of Worker and set its parentObject to the Worker instance. This way, both will always have the same thread affinity. Then, connect it to a slot, like Worker::timeoutSlot(). There you can emit your finish signal.
I want to create a program by using Qt framework. The aim is to write a program which uses QThread to show a simple digital clock. but nothing happened when running.
This is the subclass of Qthread for running
paytamtimers.h
#ifndef PAYTAMTIMERS_H
#define PAYTAMTIMERS_H
#include <QThread>
class PaytamTimers:public QThread
{
Q_OBJECT
public:
PaytamTimers();
QString now;
protected:
virtual void run();
private:
QMutex mutex;
QThread *thread;
signals:
void mySignal(QString);
};
#endif // PAYTAMTIMERS_H
and this is the implementation of this.class
paytamtimers.cpp
#include "paytamtimers.h"
#include <QTime>
PaytamTimers::PaytamTimers()
{
this->now="";
this->thread=new QThread(0);
}
void PaytamTimers::run(){
forever{
mutex.lock();
this->now=QTime::currentTime().toString();
this->thread->sleep(1000);
emit mySignal(this->now);
mutex.unlock();
}
}
and this is the implementation of GUI form. This for consist of QLabel and an instance of paytamtimers,just for simplity
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "paytamtimers.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
t=new PaytamTimers();
t->start();
connect(t,SIGNAL(t->mySignal(QString)),this,SLOT(this->now(const QString &string)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::now(const QString &string){
this->ui->label->setText(t->now);
}
You should not hold the mutex while sleeping in the thread. In fact, your mutex is completely unnecessary.
Your connect statement is wrong, as noted by hyde. The this parameter is implied, so you could simply say:
connect(t, SIGNAL(mySignal(QString)), SLOT(now(QString)));
You don't need to use a thread in order to emit periodic time updates.
Your MainWindow could look like below. It'll take care to fire the timer event as close to full second as possible.
class MainWindow : public QWidget {
Q_OBJECT
QBasicTimer m_timer;
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == m_timer.timerId()) {
QTime t = QTime::currentTime();
m_timer.start(1000 - t.msec(), this);
// round to nearest second
if (t.msec() < 500) t = t.addMsecs(-t.msec()); else t = t.addMSecs(1000-t.msec());
now(t.toString());
}
}
void now(const QString &);
...
public:
MainWindow(QWidget *parent = 0) : QWidget(parent) {
m_timer.start(1000 - QTime::currentTime().msec(), this);
}
};
Your connect statement is wrong, it should be:
connect(t, SIGNAL(mySignal(QString)), this, SLOT(now(QString)));
To catch problems like this, first of all check console output, there you should see a warning about failing connect. And another thing, use Qt Creator autocompletion to fill in SIGNAL and SLOT macros, because it is very easy to make stupid mistakes, which will not be spotted by compiler.
There are a few other funny things, such as the seemingly useless extra QThread* member variable in your QThread subclass, and an unnecessary mutex, but these shouldn't stop things from working.
In general, it seems you're just learning Qt. I'd leave threads for later, they have a lot of small gotchas and details, and worrying about them while also learning the Qt basics will not make life easy.
I would like to run a timer inside a QThread. I have written some code in which i am getting some error during the run time. Please guide me into the right direction. What am I doing wrong?
(Parent is QThread(0x1498d10), parent's thread is QThread(0x11272b0), current thread is QThread(0x1498d10)
mainwindow.h //main .h file
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "mythread.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
MyThread *myt;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp //main .cpp file
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myt=new MyThread();
myt->start();
MainWindow w;
}
MainWindow::~MainWindow()
{
delete ui;
}
mythread.h // class for thread
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QTimer>
class MyThread:public QThread
{
public:
MyThread();
void run();
QTimer *thr;
public slots:
void slo();
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
MyThread::MyThread()
{
thr= new QTimer();
connect(thr,SIGNAL(timeout()),this,SLOT(slo()));
}
void MyThread::run()
{
thr->start(1000);
}
void MyThread::slo()
{
int i,j=0;
i=i+j;
}
Just my humble opinion - Do not to subclass QThread anymore, when you do not need to.
I think, you just want to run your class in new thread or more probably you do not want to block other tasks. Your class is not thread itself. Subclassing basically means that your class IS what you are subclassing.
In other words: Let QThread do its job and concentrate on your class to do what it should do.
Example: MyClass itself does not know anything about threads. It just do what it has to do. Incrementing value and showing results ( plus some sleep part to show how it can block other functions or gui )
Header file
#include <QTimer>
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(bool willSleep, QString name, QObject *parent = 0);
public slots:
void updateCount();
private:
QTimer *timer;
int count;
bool m_wantToSleep;
};
Implementation
#include "myclass.h"
#include <QDebug>
MyClass::MyClass(bool wantToSleep, QString name, QObject *parent) :
QObject(parent)
{
this->setObjectName(name);
m_wantToSleep = wantToSleep;
count = 0;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateCount()));
timer->start(100);
}
void MyClass::updateCount()
{
++count;
qDebug() << objectName() << " count: " << count;
if (m_wantToSleep)
sleep(1);
}
We have code which does the job.
Now implement more threads - its very simple ( memory management, etc not handled to have simple example )
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThread *thread1 = new QThread; // First thread
QThread *thread2 = new QThread; // Second thread
thread1->start();
thread2->start();
MyClass *myClass = new MyClass(false, "normal class");
MyClass *mySleepClass = new MyClass(true, "sleeper class");
// Better to implement start slot to start timer ( not implemented )
// connect(thread1, SIGNAL(started), myClass, SLOT(start()));
// but this suffice, because timer will emit first signal after class is moved to another thred
//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
}
MainWindow::~MainWindow()
{
delete ui;
}
Now we can play with threads:
Blocking GUI ( of course we do not want this )
Initial example works without using new threads. Objects are in current thread and that's why GUI will be blocked. ( since I use sleep function in one instance )
//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
Non blocking GUI
We have two more threads running. Why not to use them. In example QThreads are already running, but they play with nothing. Let's move our instances there, to ensure main loop, where GUI is living will not be blocked anymore.
Magic function is moveToThread
Uncomment lines and you can see, that GUI will not be blocked. Both instances are in new thread. But then again, there is a sleep function so One should be counting faster then other. But it is not. Because they are blocking each other. They are in one thread.
mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread1);
Results in both previous cases should be: ( instances lives in same thread and shares the same event loop, so they are blocking each other )
"normal class" count: 1
"sleeper class" count: 1
"normal class" count: 2
"sleeper class" count: 2
"normal class" count: 3
"sleeper class" count: 3
So move them to separate thread
Now GUI is not blocked, niether instances each other.
mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread2);
Results should be: ( and GUI should not be blocked )
"sleeper class" count: 1
"normal class" count: 1
"normal class" count: 2
"normal class" count: 3
"normal class" count: 4
"normal class" count: 5
Hope It was understandable. As for me, this is more logic aproach then subclassing.
Of course you can create QThread in your MyClass, it is not necessary to create it oustide MyClass, I just wanted to show, that you can create one thread and move there more instances.
For anyone who disagree, I just wanted to say that: MyClass is counter with thread support sounds better then: MyClass is thread with counter ability :)
Your timer does not belong to your thread. You should create it in your run() method or you should call tmer->moveToThread before connecting it to slots, but after thread was started.
Check it: MyThread belongs to your main thread. You create timer in constructor of MyThread - so timer belongs to main thread too. But you are trying to initialize and use it in ::run method, that belongs to other thread.
In order to do this, you need to have event loop in your thread.
From QTimer's man page:
In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
From QThread's man page:
int QThread::exec () [protected]
Enters the event loop and waits until exit() is called, returning the value that was passed to exit(). The value returned is 0 if exit() is called via quit().
It is necessary to call this function to start event handling.
Also, you need to have Q_OBJECT in your class:
class MyThread:public QThread
{
Q_OBJECT
And finally, as Dmitry noted, you need to create QTimer inside your thread, so the entire cpp file should look like this:
#include "mythread.h"
MyThread::MyThread()
{
}
void MyThread::run()
{
thr= new QTimer();
connect(thr,SIGNAL(timeout()),this,SLOT(slo()));
thr->start(1000);
exec();
}
void MyThread::slo()
{
int i = 0,j=0;
i=i+j;
}
Also, read this document.
I was able to create a simple example that starts a timer within another thread, using lambda functions. Here is the code:
#include <QCoreApplication>
#include <QObject>
#include <QTimer>
#include <QThread>
#include <QDebug>
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
QThread* thread = new QThread(&app);
QObject::connect(thread, &QThread::started, [=]()
{
qInfo() << "Thread started";
QTimer* timer1 = new QTimer(thread);
timer1->setInterval(100);
QObject::connect(timer1, &QTimer::timeout, [=]()
{
qInfo() << "Timer1 " << QThread::currentThreadId();
});
timer1->start();
});
thread->start();
QTimer timer2(&app);
QObject::connect(&timer2, &QTimer::timeout, [=]()
{
qInfo() << "Timer2 " << QThread::currentThreadId();
});
timer2.setInterval(100);
timer2.start();
return app.exec();
}
I'm new to StackOverflow and wondering if I'm doing this right:
I'm writing a simple Qt application to test multi-threading (something I am also completely new to). I made a MainWindow that contains widgets, and a class MyThread that subclasses QThread and overrides the run() method.
The application simply displays two buttons, "Start Counter" and "Stop Counter", and a text field. When "start counter" is pressed, a worker thread is created and runs in the background, continuously incrementing a counter in a while loop and signaling the main thread (where the GUI is) with the updated value. When "Stop Counter" is pressed, a signal is sent to the main thread that stops the while loop, and the counter is stopped until "Start Counter" is pressed again.
This works perfectly fine ... but is it the best way? I'm new at this, and read a lot of people saying "don't subclass QThread" and other people saying "subclass QThread", and it's a little bit confusing. If this isn't the best way to implement this sort of thing (run a computationally-intensive loop in a background thread with "start" and "stop" buttons), what is? If I'm doing it wrong, how do I do it right? I don't want to learn the wrong way.
Thank you! And here's the code:
MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QMutex>
class MyThread : public QThread
{
Q_OBJECT
public slots:
void stopRunning();
protected:
virtual void run();
signals:
void signalValueUpdated(QString);
private:
bool isRunning;
};
MyThread.cpp
#include "MyThread.h"
#include <QString>
void MyThread::run()
{
qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
static int value=0; //If this is not static, then it is reset to 0 every time this function is called.
isRunning = 1;
while(isRunning == 1)
{
QString string = QString("value: %1").arg(value++);
sleep(1/1000); //If this isn't here, the counter increments way too fast and dies, or something; the app freezes, anyway.
emit signalValueUpdated(string);
}
}
void MyThread::stopRunning()
{
isRunning = 0;
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QApplication>
#include <QPushButton>
#include <QHBoxLayout>
#include <QLineEdit>
#include "MyThread.h"
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
private:
//Widgets
QHBoxLayout * boxLayout;
QPushButton * startButton;
QPushButton * stopButton;
QLineEdit * lineEdit;
MyThread thread;
};
#endif
MainWindow.cpp
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
boxLayout = new QHBoxLayout(this);
startButton = new QPushButton("Start Counter", this);
stopButton = new QPushButton("Stop Counter", this);
lineEdit = new QLineEdit(this);
boxLayout->addWidget(startButton);
boxLayout->addWidget(stopButton);
boxLayout->addWidget(lineEdit);
qDebug("Thread id %d",(int)QThread::currentThreadId());
//When the start button is pressed, invoke the start() method in the counter thread
QObject::connect(startButton,SIGNAL(clicked()),&thread,SLOT(start()), Qt::QueuedConnection);
//When the stop button is pressed, invoke the stop() method in the counter thread
QObject::connect(stopButton,SIGNAL(clicked()),&thread,SLOT(stopRunning()), Qt::QueuedConnection);
//When the counter thread emits a signal saying its value has been updated, reflect that change in the lineEdit field.
QObject::connect(&thread,SIGNAL(signalValueUpdated(const QString&)),lineEdit,SLOT(setText(const QString&)), Qt::QueuedConnection);
}
Most of the time QThread sub-classing is a wrong way to do threading in Qt. I suggest you to read an article about threads, event loops and other which could give you an idea how to use threads in Qt in a better way. But do not listen to anyone who arguing that there is the only one right way to use QThread. There are 2 ways and while subclassing is not needed in general it could be useful sometimes. You just need to use non-subclassing way until you really need to subclass. In your particular case you don't need subclassing.
Replace sleep(1/1000); with msleep(100); Things will be just fine :)