I want to run two threads concurrently. I successfully did the same when I ran a program as a QT console application.
Here's the working code of QT console application for multi threading:-
myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
#include <QDebug>
#include <QThread>
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0);
void doSetup(QThread &cThread);
void doSetup2(QThread &cThread2);
signals:
public slots:
void doWork();
void doWork2();
};
#endif // MYOBJECT_H
main.cpp:
#include <QtCore/QCoreApplication>
#include <QThread>
#include <myobject.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThread cThread, cThread2;
MyObject cObject, cObject2;
cObject.doSetup(cThread);
cObject.moveToThread(&cThread);
cObject2.doSetup2(cThread2);
cObject2.moveToThread(&cThread2);
cThread.start();
cThread2.start();
qDebug()<<"hello there ";
return a.exec();
}
my object.cpp
#include "myobject.h"
#include <QThread>
#include "tftpServer.h"
MyObject::MyObject(QObject *parent) :
QObject(parent)
{
}
void MyObject::doSetup(QThread &cThread)
{
connect(&cThread, SIGNAL(started()), this, SLOT(doWork()));
}
void MyObject::doSetup2(QThread &cThread2)
{
connect(&cThread2, SIGNAL(started()), this, SLOT(doWork2()));
}
void MyObject::doWork()
{
for(int i=0; i<1000; i++)
{
qDebug()<<"******************Thread 1";
}
}
void MyObject::doWork2()
{
for(int i=1000; i<2000; i++)
{
qDebug()<<"Thread 2************************";
}
}
Here's the output:
******************Thread 1
Thread 2************************
******************Thread 1
Thread 2************************
******************Thread 1
Thread 2************************
******************Thread 1
Thread 2************************
..and so on
Now when I use this almost same code and run as a QT GUI application, the threads do not run concurrently, but run one after the other. Here's the code:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QThread>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void doSetup(QThread &cThread);
void doSetup2(QThread &cThread2);
private:
Ui::MainWindow *ui;
public slots:
void doWork();
void doWork2();
};
#endif // MAINWINDOW_H
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QThread>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QThread cThread, cThread2;
MainWindow cObject, cObject2;
cObject.doSetup(cThread);
cObject.moveToThread(&cThread);
cObject2.doSetup2(cThread2);
cObject2.moveToThread(&cThread2);
cThread.start();
cThread2.start();
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <qthread.h>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qDebug()<<"gui running";
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::doSetup(QThread &cThread)
{
connect(&cThread, SIGNAL(started()), this, SLOT(doWork()));
}
void MainWindow::doSetup2(QThread &cThread2)
{
connect(&cThread2, SIGNAL(started()), this, SLOT(doWork2()));
}
void MainWindow::doWork()
{
//QThread::sleep(100);
for(int i=0; i<1000; i++)
{
qDebug()<<"******************Thread 1";
// qDebug()<<i;
}
}
void MainWindow::doWork2()
{
for(int i=1000; i<2000; i++)
{
qDebug()<<"Thread 2************************";
// qDebug()<<i;
}
}
Here's the output:
gui running
gui running
QObject::moveToThread: Widgets cannot be moved to a new thread
QObject::moveToThread: Widgets cannot be moved to a new thread
gui running
******************Thread 1
******************Thread 1
******************Thread 1
******************Thread 1
(and so on...)
******************Thread 1
Thread 2************************
Thread 2************************
Thread 2************************
Thread 2************************
Thread 2************************
Thread 2************************
(and so on...)
Note that the only difference b/w console and gui application I made is changed the base class QObject to QMainWindow, and hence the thread objects so created are objects of QObject & QMainWindow respectively, for console and GUI applications.
Hoping I am sufficiently clear, can you please tell me what mistake am I committing, which is making the threads run one after the other and not concurrently, as it does for the console application?
Thank you.
Any class inherited from QWidget cannot reside in thread other than the main GUI thread. Actually this is what the output said. Your solution is a bad design. Separate the work objects (inherited from QObject, residing in another thread) and the visual objects (inherited from QWidget, residing in the GUI thread), to follow the "one class one responsibility" principle.
Another catch in multithreading in Qt is the fact that any QObject cannot reside in different thread than its parent. This is natural because the parent is the owner of the child object, most importantly it takes care of its destruction. To enable this, the child cannot be in other thread. Otherwise the parent might destroy an executing child, for example.
There are yet more catches, for example QPixmap cannot be in other thread than the main GUI etc.
Related
In my App I have some problems with threads and GUI messages like QMessageBox or a new dialog. To reproduce I made a small app to show the problem:
mainwindow.cpp
#include <QDebug>
#include "mainwindow.h"
#include "ui_mainwindow.h"
void ThreadAddTree::run() {
//mClass->addTreeEx();
bool b = false;
emit addTree(&b);
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString path = "";
mThreadAddTree = new ThreadAddTree(this, path);
connect(mThreadAddTree, SIGNAL(addTree(bool*)), this, SLOT(on_add_tree(bool*)), Qt::BlockingQueuedConnection);
//,Qt::DirectConnection
mThreadAddTree->start();
}
void MainWindow::on_add_tree(bool* newData) {
QMessageBox::information(this, tr("Information"),
tr("Button click!"));
*newData = true;
}
void MainWindow::addTreeEx()
{
QMessageBox::information(this, tr("Information"),
tr("Button click!"));
}
Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtWidgets>
#include <QThread>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class ThreadAddTree : public QThread
{
Q_OBJECT
public:
ThreadAddTree(class MainWindow *nClass, const QString &path) {
mPath = path;
mClass = nClass;
}
signals:
void addTree(bool*);
protected:
void run();
QString mPath;
class MainWindow *mClass;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
friend class ThreadAddTree;
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void addTreeEx();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
protected:
ThreadAddTree *mThreadAddTree;
protected Q_SLOTS:
void on_add_tree(bool* newData);
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
If I use in Thread the call: mClass->addTreeEx(); the app will crash, in case of non main GUI thread. Understood.
So I uncouple the call with emit a message emit addTree(&b); works well. Messagebox is shown and no crash.
But now it becomes complicated for me. I need to call mClass->addTreeEx(); in my app because it will do a couple of operations. The same function is also used outside an additional thread.
But in one case, the mClass->addTreeEx(); that is running inside the thread need to call the Messagebox.
So my question is here, how to manage, that I can emit the emit addTree(&b); from the function mClass->addTreeEx(); if it was called from the thread and the app will not crash in case of no GUI thread?
Interpreting the code author's intent (to degree) and open to be corrected.
The signal parameter of type bool* in void addTree(bool*); makes not much sense especially for the case with signal sender having the boolean variable on the stack. Either make it void addTree(bool) and send immediate value or just void addTree() and handle the boolean atomic flag on the slot side as std::atomic_bool thread_safe_flag; so checking on that flag will be as actual as possible if (thread_safe_flag). But such handling requires even more to ensure the signal delivered at the right time in sync with the value. This is irrelevant to Qt, though: Why do I need to acquire a lock to modify a shared "atomic" variable before notifying condition_variable and can be done either with or without Qt.
The problem of message box on UI thread preventing the other message box from appearing (this is again an interpretation of the author's problem with the code). We obviously need to have a handle operate the message box, say, dismiss it, in case if it is open already:
QMessageBox* m_msgBoxPtr{nullptr};
std::atomic_bool m_threadSafeFlag;
void UI_Class::mySlotToHandleMsgBox()
{
if (m_msgBoxPtr != nullptr) {
m_msgBoxPtr->close();
m_msgBoxPtr->deleteLater();
m_msgBoxPtr = nullptr;
mySlotToHandleMsgBox();
}
else {
m_msgBoxPtr = new QMessageBox(QMessageBox::Information, title, message);
m_msgBoxPtr->exec(); // assuming we want modal dialog as QMessageBox::information()
// otherwise do m_msgBoxPtr->show()
// if this is set on UI thread only then and no
// "waits" for it on other threads then it being atomic is enough;
// then don't bother with any sync "complications"
m_threadSafeFlag = true;
}
}
mainworker.h
#ifndef MAINWORKER_H
#define MAINWORKER_H
#include <QObject>
class MainWorker : public QObject
{
Q_OBJECT
signals:
void completed(void);
public slots:
void run(void);
};
#endif // MAINWORKER_H
mainworker.cpp
#include "mainworker.h"
#include <QThread>
void MainWorker::run(void)
{
QThread::sleep(1);
emit completed();
}
mainthread.h
#ifndef MAINTHREAD_H
#define MAINTHREAD_H
#include <QThread>
class MainThread : public QThread
{
Q_OBJECT
public:
MainThread(void);
};
#endif // MAINTHREAD_H
mainthread.cpp
#include "mainthread.h"
MainThread::MainThread(void)
: QThread(nullptr)
{
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(void);
signals:
void runJob(void);
public slots:
void jobCompleted(void);
private:
QPushButton m_runButton;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QMessageBox>
MainWindow::MainWindow(void)
: QMainWindow(nullptr),
m_runButton(this)
{
connect(&m_runButton, SIGNAL(released()), this, SIGNAL(runJob()));
m_runButton.setText("RUN!");
setCentralWidget(&m_runButton);
}
void MainWindow::jobCompleted(void)
{
QMessageBox::information(this, tr("Info"), tr("Job completed!"));
}
main.cpp
#include <QApplication>
#include "mainwindow.h"
#include "mainthread.h"
#include "mainworker.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow window;
MainThread thread;
MainWorker worker;
worker.connect(&window, SIGNAL(runJob()), &worker, SLOT(run()));
window.connect(&worker, SIGNAL(completed()), &window, SLOT(jobCompleted()));
worker.moveToThread(&thread);
thread.start();
window.show();
int exitCode = a.exec();
thread.quit();
thread.wait();
return exitCode;
}
Of course you can add args to signals and slots and call jobCompleted() slot any time from GUI thread.
I'm writing a QT application and everything is fine with building and working but when i close the app with a thread running, the app closes and shows a message:
[Runtime Error....].
The application output says:
QThread: Destroyed while thread is still running
The program has unexpectedly finished.
The process was ended forcefully.
example crashed.
how to solve that ?
Example:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QString>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
example = new Thread(this);
connect(example, SIGNAL(print_line(QString)), this, SLOT(print_line2(QString)), Qt::BlockingQueuedConnection);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::print_line2(QString in)
{
ui->textBrowser->append(in);
}
void MainWindow::on_pushButton_clicked()
{
example->start();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <Thread.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Thread *example;
public slots:
void print_line2(QString in);
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Thread.cpp
#include "Thread.h"
#include <windows.h>
using namespace std;
Thread::Thread(QObject *parent):
QThread(parent)
{
}
Thread::~QThread()
{
delete ui;
}
void Thread::print(QString in)
{
print_line(in);
}
void Thread::run()
{
int count = 0;
for(;;) {
Sleep(100);
count += 1;
print(QString::number(count));
}
}
Thread.h
#ifndef READINFO_H
#define READINFO_H
#include <QThread>
class Thread : public QThread
{
Q_OBJECT
public:
explicit Thread(QObject *parent =0);
void print(QString in);
void run();
signals:
void print_line(QString x);
};
#endif
Ready example
The problem is that the thread is still in the running state when your application shuts down.
The code inside Thread::Run() contains an infinite loop -- there is no way for it to terminate by itself. You need to write your thread so that it will exit, or at the very least, you need to forcefully terminate the thread before your app closes.
To forcefully terminate, you could add two lines of code to the MainWindow destructor like so:
MainWindow::~MainWindow()
{
example->terminate();
example->wait();
(...)
}
I cannot produce a very simple example to getting start with Qt multi-thread. I read a lot of posts and tutorials but still it doesn't work.
Goal
Have a background worker independent from the GUI. Oh, wow...
What I did
A simple example:
create the Engine class
that shows a QMainWindow
and starts a QTimer that prints a number
But if you left-click the title bar of the GUI, keeping pressed the mouse button (i.e. on the minimize button) the counter will stop! Even if it was created in a non-GUI environment and it was moved in another thread!
Why?
main.cpp
#include "engine.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Engine e;
return a.exec();
}
engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <QObject>
#include <QThread>
#include <QTimer>
#include "mainwindow.h"
class Engine : public QObject
{
Q_OBJECT
public:
explicit Engine(QObject *parent = 0);
private:
MainWindow mainWindow;
QThread *thread;
QTimer *timer;
private slots:
void foo();
};
#endif // ENGINE_H
engine.c
#include "engine.h"
#include <QDebug>
Engine::Engine(QObject *parent) : QObject(parent)
{
thread = new QThread(this);
timer = new QTimer();
timer->setInterval(100);
connect(timer, &QTimer::timeout, this, &Engine::foo);
connect(thread, &QThread::started, timer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
timer->moveToThread(thread);
thread->start();
mainWindow.show();
}
void Engine::foo()
{
static int i;
qDebug() << ++i;
}
The QMainWindow contains no code.
Basically, Qt has one thread dealing with the GUI (typically the main thread). Any objects specific to this thread will be blocked by GUI work. You need to keep the GUI outside of your interacting partners.
To be more specific, your Engine object resides in the GUI/main thread. Even while your timer is sent to a worker thread, its signals are dispatched to the slot foo() in the main thread.
You need to de-mangle Engine and the main window such that Engine can reside in its own thread and process signals while the GUI is blocking.
Looks like you moved QTimer instance to your custom thread, but you didnt move Engine instance to this thread, therefore, foo slot of Engine class will be executed in main thread.
I can suggest you using additional helping QObject-derived class instance within Engine class and move it to your new thread in Engine constructor.
With following changes solution works fine even with minimize button pressed (I've commented places where i added or changed anything. Also added new QObject-derived class EngineWorker):
Engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <QObject>
#include <QThread>
#include <QTimer>
#include "mainwindow.h"
#include "engineworker.h"
class Engine : public QObject
{
Q_OBJECT
public:
explicit Engine(QObject *parent = 0);
private:
MainWindow mainWindow;
QThread *thread;
QTimer *timer;
//additional QObject-derived class
EngineWorker *worker;
private slots:
void foo();
};
#endif // ENGINE_H
Engine.cpp
#include "engine.h"
#include <QDebug>
Engine::Engine(QObject *parent) : QObject(parent)
{
thread = new QThread(this);
timer = new QTimer();
//Creating instance of Engine worker
worker = new EngineWorker();
timer->setInterval(100);
//Connecting Engine worker' foo slot to timer
connect(timer, &QTimer::timeout, worker, &EngineWorker::foo);
connect(thread, &QThread::started, timer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
timer->moveToThread(thread);
//Moving worker to custom thread
worker->moveToThread(thread);
thread->start();
mainWindow.show();
}
void Engine::foo()
{
static int i;
qDebug() << ++i;
}
EngineWorker.h
#ifndef ENGINEWORKER_H
#define ENGINEWORKER_H
#include <QObject>
#include <QDebug>
class EngineWorker : public QObject
{
Q_OBJECT
public:
explicit EngineWorker(QObject *parent = 0);
signals:
public slots:
void foo();
};
#endif // ENGINEWORKER_H
EngineWorker.cpp
#include "engineworker.h"
EngineWorker::EngineWorker(QObject *parent) : QObject(parent)
{
}
//foo slot of EngineWorker class
void EngineWorker::foo()
{
static int j;
qDebug() <<"Worker: "<< ++j;
}
I'm developing C++ application in QT with GUI. To make the GUI always respond, I create a thread for other blocking process. However, the application is waiting for the blocking process and therefore the GUI didn't respond.
Is creating a thread for blocking process is a wrong way?
Or it doesn't work in QT? If so, how to make the GUI respond? Please give me example.
This is a simple example of multithreaded application with responsive GUI:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QLineEdit>
#include <QThread>
class Worker : public QThread
{
protected:
/// Wait 3s which simulates time demanding job.
void run() { sleep(3); }
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
public slots:
void doJob(bool);
void jobFinished();
private:
Worker worker;
QLineEdit *line;
QPushButton *button;
int counter;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
line(new QLineEdit()),
button(new QPushButton()),
counter(0)
{
line->setDisabled(true);
line->setAlignment(Qt::AlignRight);
line->setText(QString::number(counter));
button->setText("Push");
connect(button, SIGNAL(clicked(bool)), this, SLOT(doJob(bool)));
connect(&worker, SIGNAL(finished()), this, SLOT(jobFinished()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(line);
layout->addWidget(button);
QWidget *window = new QWidget();
window->setLayout(layout);
setCentralWidget(window);
}
void MainWindow::doJob(bool)
{
// Only one thread is running at a time.
// If you want a thread pool, the implementation is up to you :)
worker.start();
// Uncomment to wait. If waiting, GUI is not responsive.
//worker.wait();
}
void MainWindow::jobFinished()
{
++counter;
line->setText(QString::number(counter));
}
Qt has a very good multithreading support. You probably do something wrong and we can't help you if you don't provide any code. There are a lot of ways of implementing "responsive" GUI! (Including a lot of ways how to implement another thread!)
I would like to create a class that has its own QTimer and QThread for some projects for Robot's sensors. After some searching, this is what I came up with
#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QObject>
#include <QDebug>
//#####################( Robot Class )#########################3
class Robot : public QObject
{
public:
Robot(QObject *parent = 0);
~Robot();
private:
QTimer *mQTimer;
QThread *mQThread;
public slots:
void update();
};
Robot::Robot(QObject *parent)
: QObject(parent)
{
mQTimer = new QTimer(0);
mQThread = new QThread(this);
mQTimer->setInterval(1);
mQTimer->moveToThread(mQThread);
connect(mQTimer, SIGNAL(timeout()), this, SLOT(update()));
connect(mQThread, SIGNAL(started()), mQTimer, SLOT(start()));
mQThread->start();
//mQTimer->start();
}
Robot::~Robot()
{
delete mQTimer;
delete mQThread;
}
void Robot::update()
{
qDebug() << "Robot is updating ...";
}
//##################( Main )###########################
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Robot *myRobot = new Robot(0);
return a.exec();
}
I'm getting this error
QObject::connect: No such slot QObject::update() in ..\untitled1\main.cpp:34
QObject::connect: No such slot QObject::update() in ..\untitled1\main.cpp:34
You are missing the Q_OBJECT macro in your class also try to avoid naming the methods like that because you can mix it with Qt methods names. Also make additional header and cpp file for each class you create in this case make robtot.h and robot.cpp.
class Robot : public QObject
{
Q_OBJECT
public:
Robot(QObject *parent = 0);
~Robot();
...
The below works for me. You forgot the Q_OBJECT macro and to include the moc output that defines the static metadata for Robot.
There's of course no point to this code, since the Robot::update slot will execute in the main thread.
Your code has two threads: the main thread, where the Robot object lives, and the robot.mThread, where the timer lives. The timer will time out in the mThread, and will queue a slot call on the main thread. That slot call will end up invoking robot.update with a.exec on the stack.
Note that there's no need to explicitly have the timer and the thread allocated on the heap using new. They should be direct members of Robot, or of its PIMPL.
main.cpp
#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QDebug>
class Robot : public QObject
{
Q_OBJECT
QTimer mTimer;
QThread mThread;
public:
Robot(QObject *parent = 0) : QObject(parent) {
connect(&mTimer, &QTimer::timeout, this, &Robot::update);;
mTimer.start(1000);
mTimer.moveToThread(&mThread);
mThread.start();
}
Q_SLOT void update() {
qDebug() << "updating";
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Robot robot;
return a.exec();
}
#include "main.moc"
It would make more sense to move the entire robot to its own thread. Note that when you do that, you need to set parentage on all objects owned by robot, so that they all switch threads along with the Robot object.
The Thread class fixes the long standing usability bug of QThread - it turns it into a truly RAII class that can be safely destructed at any time.
main.cpp
#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QDebug>
class Thread : public QThread {
using QThread::run;
public:
~Thread() { quit(); wait(); }
};
class Robot : public QObject
{
Q_OBJECT
QTimer mTimer;
int mCounter;
public:
Robot(QObject *parent = 0) : QObject(parent), mTimer(this), mCounter(0) {
connect(&mTimer, &QTimer::timeout, this, &Robot::update);;
mTimer.start(1000);
}
Q_SLOT void update() {
qDebug() << "updating";
if (++mCounter > 5) qApp->exit();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Robot robot;
Thread thread;
robot.moveToThread(&thread);
thread.start();
return a.exec();
}
#include "main.moc"