Qt: using QWidgets in non GUI threads - qt

I'm trying to understand what is and isn't allowed when it comes to QWidget and Qt concurrency. I've created a Widget which has a slow_function and I'm considering three cases:
Run the slow_function on the GUI thread. This results in the expected behaviour; the GUI becomes unresponsive while waiting for the function to return.
Use QtConcurrent::run(this, &Widget::slow_function). I was surprised to see that this didn't block the GUI. I've confirmed that the thread affinity of my instance is still the GUI thread, nevertheless, the function seems to be executing on a separate thread. Is such an approach allowed and is this the expected behaviour (documentation link would be really helpful)? Is such an approach safe if I can guarantee that slow_function is thread-safe?
Create a subclass of QThread which holds a pointer to my widget. Override the run method to call slow_function. The behaviour is the same as Case 2. This is also surprising as the thread affinity is still the GUI thread (besides, we are not even allowed to use moveToThread on a QWidget). Why is this running on a separate thread? Is moveToThread meant to be useful only when we are interested in calling slots via signals sent from another thread?
Thank you for reading. Here is the relevant code starting with my the header file:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include <QPushButton>
#include <QLayout>
#include <windows.h>
#include <QtConcurrent/QtConcurrent>
#include <QThread>
#include <QApplication>
class Widget;
class Thread: public QThread
{
public:
Thread(Widget* widget)
: m_widget(widget){}
protected:
void run() override;
private:
Widget* m_widget;
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget* parent = nullptr)
: QWidget(parent)
, m_thread(this){
auto layout = new QVBoxLayout(this);
auto button = new QPushButton("Case 1: Run on gui thread");
auto button2 = new QPushButton("Case 2: Run with qtconcurrent");
auto button3 = new QPushButton("Case 3: Run with qthread");
connect(button, &QPushButton::clicked, this, &Widget::slow_function);
connect(button2, &QPushButton::clicked, this, &Widget::use_concurrent);
connect(button3, &QPushButton::clicked, this, &Widget::use_qthread);
layout->addWidget(button);
layout->addWidget(button2);
layout->addWidget(button3);
}
~Widget()
{
m_thread.quit();
m_thread.wait();
}
public slots:
void slow_function()
{
qDebug() << "Starting";
auto gui_thread = QApplication::instance()->thread();
auto this_thread = thread();
qDebug() << "Thread affinity is" << (gui_thread == this_thread ? "gui_thread" : "non_gui_thread");
Sleep(5000);
qDebug() << "Finished";
}
void use_concurrent()
{
QtConcurrent::run(this, &Widget::slow_function);
}
void use_qthread()
{
m_thread.start();
}
private:
Thread m_thread;
};
#endif // WIDGET_H
and the main.cpp file:
#include "widget.h"
#include <QApplication>
void Thread::run()
{
m_widget->slow_function();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}

You should not do any UI things in nonmain threads. The UI means
widget interaction
model
Run the slow_function on the GUI thread
That's not allowed, nothing should block the GUI thread.
Is such an approach safe if I can guarantee that slow_function is thread-safe?
It's okay to run slow function in a different thread. But...
what happens when the user closes the application, but the function still executes?
I have done this, but I prefer to encapsulate it in a separate class.
Create a subclass of QThread which holds a pointer to my widget.
You should only subclass QThread if the subclass is a thread. Like, subclassing an animal class will give you an animal, not a chair with four legs.
Is moveToThread meant to be useful only when we are interested in calling slots via signals sent from another thread?
moveToThread changes the affinity of the object. So, slots are always executed in the correct thread, when you call invokeMethod, the method is executed in the correct thread. When an event is delivered, the event handler is always called in the appropriate thread.

The whole purpose of QtConcurrent::run() is to make running heavy workloads in a thread easier. If your use-case allows for it, great!
Pair it with a QFutureWatcher to retrieve the result after your slow_function is finished.
Using QThread is another option, but it makes more sense when you have a long-lived object. Instead of subclassing, I find it easier to use the worker model: create a worker class with signals/slots, call moveToThread on it with a vanilla QThread object, connect/subscribe, start the thread
QWidget is a way to create GUI functionality in Qt. While it may be possible to use such objects in non-gui threads, it's best you separate your compute workloads from GUI (don't put your slow_function into widget classes).

Related

Using POSIX threads in Qt Widget App

I'm relatively new to both Qt and pthreads, but I'm trying to use a pthread to work in the background of basic test app I'm making. I'm aware of the Qt Frameworks own threading framework - but there's a lot of complaint surrounding it so I'd like to use pthread if possible. The code is as below
#include "drawwindow.h"
#include "ui_drawwindow.h"
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include "QThread"
pthread_t th1;
DrawWindow::DrawWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::DrawWindow)
{
ui->setupUi(this);
}
DrawWindow::~DrawWindow()
{
delete ui;
}
void DrawWindow::on_pushButton_clicked()
{
pthread_create(&th1, NULL, &DrawWindow::alter_text, NULL);
}
void DrawWindow::alter_text()
{
while(1)
{
ui->pushButton->setText("1");
QThread::sleep(1);
ui->pushButton->setText("one");
QThread::sleep(1);
}
}
With the header
#ifndef DRAWWINDOW_H
#define DRAWWINDOW_H
#include <QMainWindow>
namespace Ui {
class DrawWindow;
}
class DrawWindow : public QMainWindow
{
Q_OBJECT
public:
explicit DrawWindow(QWidget *parent = 0);
~DrawWindow();
void alter_text();
private slots:
void on_pushButton_clicked();
private:
Ui::DrawWindow *ui;
};
#endif // DRAWWINDOW_H
And I'm getting the error
error: cannot convert 'void (DrawWindow::*)()' to 'void* (*)(void*)' for argument '3' to 'int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)'
pthread_create(&th1, NULL, &DrawWindow::alter_text, NULL);
^
Does anyone know what is wrong?
TL;DR: The way you're using pthreads is precisely the discouraged way of using QThread. Just because you use a different api doesn't mean that what you're doing is OK.
There's absolutely no problem with either QThread or std::thread. Forget about pthreads: they are not portable, their API is C and thus abhorrent from a C++ programmer's perspective, and you'll be making your life miserable for no reason by sticking to pthreads.
Your real issue is that you've not understood the concerns with QThread. There are two:
Neither QThread nor std::thread are destructible at all times. Good C++ design mandates that classes are destructible at any time.
You cannot destruct a running QThread nor std::thread. You must first ensure that it's stopped, by calling, respectively QThread::wait() or std::thread::join(). It wouldn't have been a big stretch to have their destructors do that, and also stop the event loop in case of QThread.
Way too often, people use QThread by reimplementing the run method, or they use std::thread by running a functor on it. This is, of course, precisely how you use pthreads: you run some function in a dedicated thread. The way you're using pthreads is just as bad as the discouraged way of using QThread!
There are many ways of doing multithreading in Qt, and you should understand the pros and cons of each of them.
Thus, how do you do threading in C++/Qt?
First, keep in mind that threads are expensive resources, and you should ideally have no more threads in your application than the number of available CPU cores. There are some situations when you're forced to have more threads, but we'll discuss when it's the case.
Use a QThread without subclassing it. The default implementation of run() simply spins an event loop that allows the objects to run their timers and receive events and queued slot calls. Start the thread, then move some QObject instances to it. The instances will run in that thread, and can do whatever work they need done, away from the main thread. Of course, everything that the objects do should be short, run-to-completion code that doesn't block the thread.
The downside of this method is that you're unlikely to exploit all the cores in the system, as the number of threads is fixed. For any given system, you might have exactly as many as needed, but more likely you'll have too few or too many. You also have no control over how busy the threads are. Ideally, they should all be "equally" busy.
Use QtConcurrent::run. This is similar to Apple's GCD. There is a global QThreadPool. When you run a functor, one thread from the pool will be woken up and will execute the functor. The number of threads in the pool is limited to the number of cores available on the system. Using more threads than that will decrease performance.
The functors you pass to run will do self-contained tasks that would otherwise block the GUI leading to usability problems. For example, use it to load or save an image, perform a chunk of computations, etc.
Suppose you wish to have a responsible GUI that loads a multitude of images. A Loader class could do the job without blocking the GUI.
class Loader : public QObject {
Q_OBJECT
public:
Q_SIGNAL void hasImage(const QImage &, const QString & path);
explicit Loader(const QStringList & imagePaths, QObject * parent = 0) :
QObject(parent) {
QtConcurrent::map(imagePaths, [this](const QString & path){
QImage image;
image.load(path);
emit hasImage(image, path);
});
}
};
If you wish to run a short-lived QObject in a thread from the thread pool, the functor can spin the event loop as follows:
auto foo = QSharedPointer<Object>(new Object); // Object inherits QObject
foo->moveToThread(0); // prepares the object to be moved to any thread
QtConcurrent::run([foo]{
foo->moveToThread(QThread::currentThread());
QEventLoop loop;
QObject::connect(foo, &Object::finished, &loop, &QEventLoop::quit);
loop.exec();
});
This should only be done when the object is not expected to take long to finish what it's doing. It should not use timers, for example, since as long as the object is not done, it occupies an entire thread from the pool.
Use a dedicated thread to run a functor or a method. The difference between QThread and std::thread is mostly in that std::thread lets you use functors, whereas QThread requires subclassing. The pthread API is similar to std::thread, except of course that it is C and is awfully unsafe compared to the C++ APIs.
// QThread
int main() {
class MyThread : public QThread {
void run() { qDebug() << "Hello from other thread"; }
} thread;
thread.start();
thread.wait();
return 0;
}
// std::thread
int main() {
// C++98
class Functor {
void operator()() { qDebug() << "Hello from another thread"; }
} functor;
std::thread thread98(functor);
thread98.join();
// C++11
std::thread thread11([]{ qDebug() << "Hello from another thread"; });
thread11.join();
return 0;
}
// pthread
extern "C" void* functor(void*) { qDebug() << "Hello from another thread"; }
int main()
{
pthread_t thread;
pthread_create(&thread, NULL, &functor, NULL);
void * result;
pthread_join(thread, &result);
return 0;
}
So, what is this good for? Sometimes, you have no choice but to use a blocking API. Most database drivers, for example, have blocking-only APIs. They expose no way for your code to get notified when a query has been finished. The only way to use them is to run a blocking query function/method that doesn't return until the query is done. Suppose now that you're using a database in a GUI application that you wish to remain responsive. If you're running the queries from the main thread, the GUI will block each time the database query run. Given long-running queries, a congested network, a dev server with a flaky cable that makes the TCP perform on par with sneakernet... you're facing huge usability issues.
Thus, you can't but have to run the database connection on, and execute the database queries on a dedicated thread that can get blocked as much as necessary.
Even then, it might still be helpful to use some QObject on the thread, and spin an event loop, since this will allow you to easily queue the database requests without having to write your own thread-safe queue. Qt's event loop already implements a nice, thread-safe event queue so you might as well use it. For example, with a note that Qt's SQL module can be used from one thread only - thus you can't prepare QSQLQuery in the main thread :(
Note that this example is very simplistic, you'd likely want to provide thread-safe way of iterating the query results, instead of pushing the entire query's worth of data at once.
class DBWorker : public QObject {
Q_OBJECT
QScopedPointer<QSqlDatabase> m_db;
QScopedPointer<QSqlQuery> m_qBooks, m_query2;
Q_SLOT void init() {
m_db.reset(new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE")));
m_db->setDatabaseName(":memory:");
if (!m_db->open()) { emit openFailed(); return; }
m_qBooks.reset(new QSqlQuery(*m_db));
m_qBooks->prepare("SELECT * FROM Books");
m_qCars.reset(new QSqlQuery(*m_db));
m_qCars->prepare("SELECT * FROM Cars");
}
QList<QVariantList> read(QSqlQuery * query) {
QList<QVariantList> result;
result.reserve(query->size());
while (query->next()) {
QVariantList row;
auto record = query->record();
row.reserve(record.count());
for (int i = 0; i < recourd.count(); ++i)
row << query->value(i);
result << row;
}
return result;
}
public:
typedef QList<QVariantList> Books, Cars;
DBWorker(QObject * parent = 0) : QObject(parent) {
QObject src;
connect(&src, &QObject::destroyed, this, &DBWorker::init, Qt::QueuedConnection);
m_db.moveToThread(0
}
Q_SIGNAL void openFailed();
Q_SIGNAL void gotBooks(const DBWorker::Books &);
Q_SIGNAL void gotCars(const DBWorker::Cars &);
Q_SLOT void getBooks() {
Q_ASSERT(QThread::currentThread() == thread());
m_qBooks->exec();
emit gotBooks(read(m_qBooks));
}
Q_SLOT void getCars() {
Q_ASSERT(QThread::currentThread() == thread());
m_qCars->exec();
emit gotCars(read(m_qCars));
}
};
Q_REGISTER_METATYPE(DBWorker::Books);
Q_REGISTER_METATYPE(DBWorker::Cars);
// True C++ RAII thread.
Thread : public QThread { using QThread::run; public: ~Thread() { quit(); wait(); } };
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
Thread thread;
DBWorker worker;
worker.moveToThread(&thread);
QObject::connect(&worker, &DBWorker::gotCars, [](const DBWorker::Cars & cars){
qDebug() << "got cars:" << cars;
qApp->quit();
});
thread.start();
...
QMetaObject::invokeMethod(&worker, "getBooks"); // safely invoke `getBooks`
return app.exec();
}
Change void DrawWindow::alter_text() to void* DrawWindow::alter_text(void*) and return pthread_exit(NULL);.

How to hide a QDialog (not showing GUI) on exec()

I want to exec() a QDialog without GUI for my test - there's no need to show GUI.
In the main window, when I exec() a QDialog, it shows its GUI window. I connect a signal from thread in QDialog to a slot in QDialog, so QDialog.exec() is needed. QDialog.hide() is not working.
Is there any solution?
You should never exec() a dialog. This can lead to subtle bugs, because the exec() call can reenter code you don't plan on being reentered.
If you really insist on using exec(), then the simple solution is to post a CloseEvent to the dialog. The event will be processed once the dialog's event loop starts running.
MyDialog dialog;
QCoreApplication::postEvent(&dialog, new QCloseEvent());
dialog.exec();
This code is functionally equivalent to the following:
MyDialog dialog;
QMetaObject::invokeMethod(&dialog, "close", Qt::QueuedConnection);
dialog.exec();
An alternative, much safer way to accomplish this is not to use exec. Simply connect the dialog's accepted() and rejected() signals to slots in your code - after all, the dialog's acceptance or rejection happens asynchronously.
It's then easy enough simply not to show() the dialog in the test code path. You can also easily simulate the dialog being accepted or rejected by invoking either accept or reject slots.
I really don't understand exactly how you "connected" signals from a thread to dialog's slots, and so on. Feel free to paste the example below into your question, modify it to do the threaded "stuff", and show how it doesn't work. It'd also help to see how you implement the test harness.
The example below is all a single file, it'd help if you would keep it that way when producing a test case that illustrates your problem.
// main.cpp
#include <QApplication>
#include <QDialog>
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QDialogButtonBox>
class MyDialog : public QDialog {
QGridLayout m_layout;
QDialogButtonBox m_box;
public:
MyDialog(QWidget * parent = 0) : QDialog(parent), m_layout(this),
m_box(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
{
m_layout.addWidget(&m_box);
connect(&m_box, SIGNAL(accepted()), SLOT(accept()));
connect(&m_box, SIGNAL(rejected()), SLOT(reject()));
}
};
class MyGui : public QWidget {
Q_OBJECT
QGridLayout m_layout;
QLabel m_label;
QPushButton m_button;
MyDialog m_dialog;
Q_SLOT void on_button_clicked() {
m_dialog.show();
}
Q_SLOT void on_dialog_accepted() {
m_label.setText("The dialog was accepted");
}
Q_SLOT void on_dialog_rejected() {
m_label.setText("The dialog was rejected");
}
public:
MyGui() : m_layout(this), m_button("Show Dialog"), m_dialog(this) {
m_button.setObjectName("button");
m_dialog.setObjectName("dialog");
m_layout.addWidget(&m_label);
m_layout.addWidget(&m_button);
QMetaObject::connectSlotsByName(this);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyGui gui;
gui.show();
return app.exec();
}
#include "main.moc"

qt5: how to create and display custom qdialog from static function within a qthread

Let's say that you've created a new thread that then calls a static function after it has been started. Within that static function you need to create and display a custom qdialog. How can you create it so that it has no parent and is located in the proper thread?
The constructor sets the parent to 0 but it still reports an error about being unable to create children for a parent in a different thread. Since it's a static function I can't use the "this" object and without "this" I can't retrieve the current thread or thread id. I thought I might be able to call myCustomDialog->moveToThread() but I have no idea how to determine the correct thread from a static function.
If I use one of the QMessageBox static functions everything works fine. For example, calling QMessageBox::information(0, tr("Title"), tr("Message")) doesn't report any errors. How can I code my custom qdialog to function similar to the qmessagebox static function?
Is there any way to retrieve a list of all running threads from the qApp object? Any other suggestions?
static int myFunction();
int myObject::myFunction()
{
myCustomDialog *mcd = new myCustomDialog();
// as soon as I call exec() it reports an error and crashes
mcd->exec();
// QObject: Cannot create children for a parent that is in a different thread.
// can't call mcd->moveToThread() without knowing the current thread
// how can I determine the current thread from this static function?
// if parent = 0 then why is this error occurring?
return 0;
}
myCustomDialog(QWidget *parent = 0);
myCustomDialog::myCustomDialog(QWidget *parent) : QDialog(parent)
{
// create widgets and layout here
}
Don't. Creating QWidget objects from another thread is a bad idea. The Documentation states:
In GUI applications, the main thread is also called the GUI thread
because it's the only thread that is allowed to perform GUI-related
operations.
The way I normally get around this is to emit a signal from my object in the non-GUI thread that's connected to an object living in the main thread (often MainWindow for me). The receiving object then creates the dialog on the main thread.
As mentioned in the other answer, this connection can block your worker thread if needed by establishing the connection type as Qt::BlockingQueuedConnection.
For more information on invoking functions from other threads, see this post.
Sample... You may adapt it to make calls from static functions, but I don't think that it is necesary. It is good practice to work with threads in next way: You should create your dialog in GUI thread and connect it's exec() slot to your signal with Qt::BlockingQueuedConnection
Worker.h
#include <QObject>
class Worker
: public QObject
{
Q_OBJECT
signals:
void showDialog();
public:
Worker( QObject *parent = NULL );
~Worker();
public slots:
void doLongWork();
private:
};
Worker.cpp
#include <QThread>
#include <QMessageBox>
#include <QDebug>
#include <QCoreApplication>
#include <Windows.h>
Worker::Worker( QObject *parent )
: QObject( parent )
{
}
Worker::~Worker()
{
}
void Worker::doLongWork() // You may override QThread::run with same effect, but it is bad practice
{
qDebug() << "Worker thread id = " << QThread::currentThreadId();
::MessageBoxA( NULL, "Click to show dialog in 3 seconds", NULL, 0 );
::Sleep( 3000 );
emit showDialog(); // "Showing" dialog from non-GUI thread. And wait for close
::MessageBoxA( NULL, "Dialog closed!", NULL, 0 );
qApp->quit();
}
main.cpp
#include <QApplication>
#include <QDialog>
#include <QThread>
#include <QDebug>
#include "Worker.h"
int main(int argc, char *argv[])
{
QApplication a( argc, argv );
a.setQuitOnLastWindowClosed( false );
QDialog dlg;
QThread workerThread;
Worker worker;
qDebug() << "Main thread id = " << QThread::currentThreadId();
QObject::connect( &workerThread, SIGNAL( started() ), &worker, SLOT( doLongWork() ) );
QObject::connect( &worker, SIGNAL( showDialog() ), &dlg, SLOT( exec() ), Qt::BlockingQueuedConnection ); // !!!See connection type!!!
worker.moveToThread( &workerThread );
workerThread.start();
return a.exec();
}
Note: WinAPI MessageBoxes are used only to visualize that thread is really waiting for close of dialog.

Why is my mainwindow closing automatically when called from a differnet class?

I can't seem to figure out what went wrong so I'm here to ask you. I have made a simple class called BOBSNetworkSessionManager defined below. It is a simple class that inherits the QOBject so that I can use signals and slots but it does not have a dialog or any kind of window associated with it. It will eventually call a log in dialog and use the credentials to connect to a tcp server that I have created. This class serves as a layer to manage the connection state of the program because it will only run properly when connected to the server and when being used within 15 minutes without break due to p.c.i. compliance. If these conditions are not true this class will lock the window and force a new login. As of right now I just try to arbitrarily open the main window as though credentials had passed and i wasbconnected to the server. The problem is when I open the mainwindow it disapears right away. I cannot seem to figure out why it is diappearing. I have included all of my files.
BOBSDCNetworkSessionManager .h header file
#ifndef BOBSDCNETWORKSESSIONMANAGER_H
#define BOBSDCNETWORKSESSIONMANAGER_H
#include <QObject>
#include <QSettings>
class BOBSDCNetworkSessionManager : public QObject
{
Q_OBJECT
public:
explicit BOBSDCNetworkSessionManager(QObject *parent = 0);
protected:
void destroyed(QObject *);
signals:
public slots:
private:
void readSettings();
void writeSettings();
QSettings networkSettings;
};
#endif // BOBSDCNETWORKSESSIONMANAGER_H
BOBSDCNetworkSessionManager Implementation .cpp file
#include "bobsdcnetworksessionmanager.h"
#include "bobsmainwindow.h"
BOBSDCNetworkSessionManager::BOBSDCNetworkSessionManager(QObject *parent) :
QObject(parent)
{
BOBSMainWindow w;
w.show();
}
Main.cpp file
#include "bobsdcnetworksessionmanager.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setApplicationName("Enterprise Management Suite");
a.setApplicationVersion("Beta Version: 0.0.0.01");
a.setOrganizationName("Enigma Web Consulting");
a.setOrganizationDomain("http://www.EnigmaWebCo.com");
BOBSDCNetworkSessionManager netMgr;
return a.exec();
}
The problem is here:
{
BOBSMainWindow w;
w.show();
}
w.show() is not a blocking call. So you're creating a window, showing it, and then it immediately is destructed when it goes out of scope. You should either declare w as a member variable or construct it on the heap:
BOBSMainWindow *w = new BOBSMainWindow(this);

Qt connect two signals together using QueuedConnection

Qt documentation states that it is possible to connect two signals together:
It is even possible to connect a signal directly to another signal.
I tried:
connect(x, SIGNAL(S()), y, SIGNAL(func()));
and it works as mentioned, but Qt documentation continues:
(This will emit the second signal immediately whenever the first is emitted.)
Does this mean that QueuedConnection will not work correctly? Can I connect two signals across threads?
The reason I am asking this is because I solved a class of crashes on an application by avoiding this, but I am not sure if this was related to connecting signals together.
It shouldn't be a great deal different from a signal/slot connection. Let's take a look at underlying mechanism of signals/slots. There is an event queue in each thread which maintains signals (events) that have been emitted but not processed yet. So whenever the execution returns to the event loop the queue is processed. Event loop itself doesn't handle the events. Rather it delivers them to the objects so they can handle it. In this special case, I suppose that the object would emit another signal which would be inserted in the queue. When the execution returns to event loop the new signal is handled by the object again. Here is a test which proves the above argument.
If you run the codes attached, the output would be:
before signal()
after signal()
slot() called
which means defining a signal-signal connection type as queued between threads have the expected queued behaviour, that rejects the argument which it is always immediate. If you define it as direct, the output would be:
before signal()
slot() called
after signal()
as expected. it doesn't generate any errors or warnings, and program doesn't crash as well.Yet this simple example doesn't prove it works for a large and complex one as well.
main.cpp:
#include <QtGui/QApplication>
#include "dialog.h"
#include "testssconnection.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TestSignalSignalConnection * t = new TestSignalSignalConnection();
t->start();
return a.exec();
}
testssconnection.h:
#ifndef TESTSSCONNECTION_H
#define TESTSSCONNECTION_H
#include <QObject>
#include <QThread>
class TestSignalSignalConnection : public QThread
{
Q_OBJECT
public:
explicit TestSignalSignalConnection(QObject *parent = 0);
void run();
signals:
void signal1();
void signal2();
public slots:
void slot();
};
#endif // TESTSSCONNECTION_H
testssconnection.cpp:
#include "testssconnection.h"
#include <QtCore>
TestSignalSignalConnection::TestSignalSignalConnection(QObject *parent) :
QThread(parent)
{
}
void TestSignalSignalConnection::run()
{
TestSignalSignalConnection *t = new TestSignalSignalConnection();
this->connect(this,SIGNAL(signal1()),t,SIGNAL(signal2()), Qt::QueuedConnection);
t->connect(t,SIGNAL(signal2()), t,SLOT(slot()), Qt::DirectConnection);
qDebug() << "before signal()";
emit signal1();
qDebug() << "after signal()";
exec();
}
void TestSignalSignalConnection::slot()
{
qDebug() << "slot() called";
}
Take a look at qt-project, its a great wiki page about Threads and signals.
Threads, Events and QObjects::Signals and slots across threads

Resources