signal and slot in QT - c++

i have a problem in working signal and slot in QT framework .
my slot is not working .
here is the code .
connect(&th,SIGNAL(change()),this,SLOT(closeWindow()));
this->moveToThread(th);
closeWindow();
th.start();
"th" is a var from a class like this :
class Thread : public QThread
{
public :
Thread();
bool pause,flag;
QString URL;
QFile *mFile;
void run();
void RESUME();
void PAUSE();
bool Check();
bool Check2();
signals:
void change();
QString myTxt;
};
"change" is the signal
and here is the code of my MainWindow :
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Thread th;
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
public slots:
void closeWindow();
};
and here is the constructor for MainWindow
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(&th,SIGNAL(change()),this,SLOT(closeWindow()));
th.start();
}
the signal is Ok . but the Slot is not Working .
can You guide me ?

I think the main issue is that the receiving object lives in a dead thread.
Your Thread instance lives on the application thread, while your MainWindow lives on the thread created by your Thread instance. However as you have reimplemented QThread::run(), you do not have an event loop on this thread and the slot can never be invoked.
Check Qt documentation for details:
Threading Basics
Threads and QObjects
Also you have some big issues in your code:
Missing Q_OBJECT macro in Thread definition (but you might have removed it while copy/pasting otherwise you wouldn't be able to emit the signal).
You must not call moveToThread() on object derived from QWidget (e.g QMainWindow). QWidgets must live on the application thread.
You generally cannot mix using moveToThread() and reimplementing run().
When using moveToThread() you are using the thread event loop to make QObjects living on this thread (i.e moved to this thread) live.
When reimplementing QThread::run(), people generally want to execute a single function on a thread. This will lead to a thread being created, the function executed and the thread destroyed without running an event loop. And no event loop mean that if a QObject lives on this thread, it will not received inter-thread slot invokations.
NB: Using moveToThread() is the correct/intended way to use QThread. Reimplementing QThread::run() will work and can be found in Qt documentation but isn't generally recommended and you might be better of using QThreadPool.
More readings: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

Related

Creating QNetworkAccessManager in another thread

I have a QNetworkAccessManager created in another thread.
The network is meant to be used only in MyMegaThread.
QNetworkAccessManager is created from the thread's run method:
mp_manager.reset(new QNetworkAccessManager{this});
On creation I get such a message in console:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is MyMegaThread(0x237eabd0ee0), parent's thread is QThread(0x237e70742a0), current thread is MyMegaThread(0x237eabd0ee0)
This message is totally harmless, but I wonder which parent the manager is supposed to have.
I suspect it happens because the MyMegaThread instance is created in the main thread, but I need a parent created in MyMegaThread instead.
What is an idiomatic way of doing this?
Parent is MyMegaThread(0x237eabd0ee0), parent's thread is
QThread(0x237e70742a0), current thread is MyMegaThread(0x237eabd0ee0)
The issue does not relate to QNetworkAccessManager.
Here is the demo to reproduce the warning.
#include <QDebug>
#include <QThread>
class MyMegaThread : public QThread
{
Q_OBJECT
public:
using QThread::QThread;
protected:
void run() override {
qDebug()<<QThread::currentThread()<<this->thread();
new QObject(this);
}
};
// main
MyMegaThread m;
m.start();
Output:
MyMegaThread(0x60fe18) QThread(0x16a7c48)
It's rule of QObject:
All QObjects must live in the same thread as their parent.
Consequently:
setParent() will fail if the two QObjects involved live in different
threads. When a QObject is moved to another thread, all its children
will be automatically moved too. moveToThread() will fail if the
QObject has a parent. If QObjects are created within QThread::run(),
they cannot become children of the QThread object because the QThread
does not live in the thread that calls QThread::run().
http://doc.qt.io/qt-5/qobject.html#thread-affinity
Have to make sure this code new QObject running QThread be same as given parent QObject thread.
mp_manager.reset(new QNetworkAccessManager{this});
No, the message is not harmless at all. The object you have created has a null parent and no reference on the thread association and thus its thread() method may return a dangling pointer at any time. It cannot safely use timers nor receive cross-thread calls. It is basically as useless object, and you're asking for undefined behavior to strike. This shouldn't be a warning, but a failure. Qt did you a disservice here by allowing you to continue.
The idiomatic way of doing it is first of all not to derive from QThread. QThread is a thread handle. It wraps a system resource. Put all of your functionality into a regular QObject moved into a QThread. The idiomatic way to endlessly "do stuff" on any thread, including the main thread, is to use a zero-duration timer. Note that zero-duration timers have nothing to do with timing at all. They are essentially event loop handles, calling them a timer is a misnomer.
To wit:
// https://github.com/KubaO/stackoverflown/tree/master/questions/thread-simple-50632807
#include <QtNetwork>
class Thread final : public QThread {
Q_OBJECT
public:
void takeObject(QObject *obj) {
obj->moveToThread(this);
}
~Thread() override {
requestInterruption();
quit();
wait();
}
};
class Class : public QObject {
Q_OBJECT
QBasicTimer m_workTimer;
QNetworkAccessManager m_manager{this};
void doWorkChunk() {
qDebug() << "tick...";
QThread::sleep(1); // emulate a blocking operation
}
protected:
void timerEvent(QTimerEvent *ev) override {
if (ev->timerId() != m_workTimer.timerId())
return;
doWorkChunk();
}
public:
explicit Class(QObject *parent = {}) : QObject(parent) {
m_workTimer.start(0, this);
}
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
Class object;
Thread workThread;
workThread.start();
workThread.takeObject(&object);
QTimer::singleShot(3000, &QCoreApplication::quit);
return app.exec();
}
#include "main.moc"
The QBasicTimer::stop: Failed. Possibly trying to stop from a different thread warning is relatively benign and indicates an internal timer handle leak. For a workaround, see this answer.

Qt 5 : update QProgressBar during QThread work via signal

I'm trying to update a QProgressDialog (owned by a QMainWindow class) along the execution of a QThread who process some time consuming operations. The thread emit some signals during operation in order to inform the calling app about progression. I'm looking to connect the progress signal emitted by the thread to the setValue slot of the QProgressDialog in order to update the progress bar.
It doesn't work ! The progress dialog is not displayed. If I add a slot in my QMainWindow and connect it to the worker progress signal in order to display the value given by the thread throught qDebug output, I see that signals seems to be stacked during the threaded operation and unstacked only at the end of the thread.
I have tryed the DirectConnection connect's option without any success.
Here is my code :
qapp.cpp
#include "qapp.h"
#include <threaded.h>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
#include <QProgressDialog>
QApp::QApp(QWidget *parent) :
QMainWindow(parent)
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
QWidget *window = new QWidget(this);
window->setLayout(mainLayout);
setCentralWidget(window);
QPushButton *button = new QPushButton("Run");
mainLayout->addWidget(button);
connect(button, SIGNAL(clicked(bool)), this, SLOT(doSomeWork()));
}
void QApp::doSomeWork()
{
qDebug() << "do some work";
Threaded worker;
worker.doHeavyCaclulations();
QProgressDialog progressDialog("Copying files...", "Abort Copy", 0, 10000, this);
progressDialog.setWindowModality(Qt::WindowModal);
progressDialog.setMinimumDuration(0);
progressDialog.setValue(0);
connect(&worker, SIGNAL(progress(int)), &progressDialog, SLOT(setValue(int)));
connect(&worker, SIGNAL(progress(int)), this, SLOT(displayProgress(int)));
worker.wait();
qDebug() << "end of thread";
}
void QApp::displayProgress(int value)
{
qDebug() << "data received" << value;
}
QApp::~QApp()
{
}
threaded.cpp :
#include "threaded.h"
#include <QDebug>
Threaded::Threaded(QObject *parent) : QThread(parent)
{
}
void Threaded::doHeavyCaclulations()
{
if (!isRunning())
{
qDebug() << "start thread" ;
start();
}
}
void Threaded::run()
{
qDebug() << "running big loop";
for(double k = 0 ; k < 10000 ; k++)
{
qDebug() << k;
emit progress(k);
}
}
qapp.h
#ifndef QAPP_H
#define QAPP_H
#include <QMainWindow>
class QApp : public QMainWindow
{
Q_OBJECT
public:
explicit QApp(QWidget *parent = 0);
~QApp();
private:
private slots:
void doSomeWork();
void displayProgress(int value);
};
#endif // QAPP_H
threaded.h
#ifndef THREADED_H
#define THREADED_H
#include <QObject>
#include <QThread>
class Threaded : public QThread
{
Q_OBJECT
public:
explicit Threaded(QObject *parent = 0);
void doHeavyCaclulations();
void run();
private:
signals:
void progress(int value);
public slots:
};
#endif // THREADED_H
The output of this code with k < 100 is :
do some work
start thread
running big loop
0
1
2
3
[...]
97
98
99
end of big loop
end of thread
data received 17
data received 18
data received 19
[...]
data received 99
If I remplace
worker.wait();
by
int k=0;
while(worker.isRunning())
{
qDebug() << "main " << k;
k++;
}
I get outputs of the thread and output of the calling method interleaved. It confirm that my thread is independant of the calling method.
Any idea about what I'm doing wrong ?
Absolutely wrong using of QThread). See what is the correct way to implement a QThread... (example please...). You need to learn thread's basics.
Your mistakes:
1. Create a static thread object in a local scope;
2. Wait for its finish in the main thread;
3. Don't start the thread;
4. Direct call method doHeavyCaclulations() in the main thread;
5. emit signal without working event loop for its deliver...
For your purpose you need:
Don't inherit QThread. Just create simple Work class with the necessary function:
class Work: public QObject
{
Q_OBJECT
public:
Work(){};
virtual ~Work(){};
public slots:
void doHeavyCaclulations() { /* do what you need and emit progress signal */ };
signals:
void progress(int);
}
// Then:
void QApp::doSomeWork()
{
//...
QThread* thread = new QThread(parent);
Work* worker = new Work; // Do not set a parent. The object cannot be moved if it has a parent.
worker->moveToThread(thread);
connect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(started()), worker, SLOT(doHeavyCaclulations()));
connect(worker, SIGNAL(progress(int)), &progressDialog, SLOT(setValue(int)));
thread->start();
//...
}
QThread has one very important thing you have to always remember when working with it - only the run() actually runs in a separate thread.
Whenever you create an instance of QThread this instance's thread affinity (the thread it belongs to) is the same thread where you have created it in. What's the big deal with that and what does it have to do with my slots and signals you may ask? Well, it has a lot to do with these things. Because only run() runs inside a separate thread you have to consider the following:
Signals belong to the instance ergo signals have a different thread affinity then the run()
Slots belong to the instance ergo slots have a different thread affinity then the run() - accessing shared data that is processed both inside a slot and inside run() requires explicitly employing thread-safety mechanisms such as mutexes and semaphores
If you do a lot of stuff inside your slots you will still freeze your UI as if you are not using your QThread
That said there are some scenarios where you may want to/have to employ slots and signals in a QThread but such implementation would have to be directed towards controlling the instance of QThread and not what it's actually running in a separate thread (using run()).
Here is a small demo I have written as a demonstration of how to implement slots and signals and interact with a separate thread using QObject. It employs slots and signals. Note that the usage of QThread is actually not necessary. You can also use a QRunnable for example (though you have to explicitly tell it to inherit from QObject too or to use a separate subclass of QObject created by you because QRunnable doesn't support slots and signals (it's not a subclass of QObject).
The advantage of using a QObject is that you can move its instance to the thread that is change it's thread affinity so that it completely runs in that separate thread (slots included). You can also put multiple QObject instances inside a single QThread if you want to. When inheriting a QThread and using it instead of this model you are limiting your options quite a bit.
So my advice here is dump the QThread implementation and go for the QThread + QObject (also know as Worker design pattern) way of doing things (for this particular scenario that is).

Using Qthread to run a function

I want to run a function of a class as a thread continuously,till the object of the class is destroyed.
client.h
class client:public QWidget
{
Q_OBJECT
public:
//some declarations
client();
void setclientui();
//some ui elements
void receiveme(); //i want this function to be run as a thread
//It has to be run continuously to receive
//messages from socket and when a message is
//received ,it must display it in the gui.
public slots:
int prework();
void sendme();
};
Note:receiveme() uses recv() of tcp sockets which gets blocked until message is received.
client.cpp
void receiveme(){
while(1){
if(recv(sockfd,receivebuf,1024,0)<0)
{
qDebug()<<errno;
break;
}
receivebuf[20]='\0';
qDebug()<<receivebuf;
outputbox->append(a);
}}
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
Dialog* newdialog;//join a new chat
QString ipp,portt;
QTabWidget *wdg;
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void receivesocketaddress();
void on_actionJoin_a_chat_triggered();
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
wdg=new QTabWidget;
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionJoin_a_chat_triggered()
{
newdialog=new Dialog();
newdialog->setWindowTitle("Join a chat");
newdialog->setModal(true);
qDebug()<< QObject::connect(newdialog->conne,SIGNAL(clicked()),this,SLOT(receivesocketaddress()));
newdialog->exec();
}
void MainWindow::receivesocketaddress()
{
client *aclient=new client;
aclient->iptoconnect=newdialog->ip->text().toLocal8Bit().data();
aclient->porti=newdialog->port->text().toLocal8Bit().data();
if(aclient->prework()==0)//ie connected
{
newdialog->close();
wdg->addTab(aclient,tr("new chat"));
setCentralWidget(wdg);
//here the ui is shown.Now the aclient->receiveme() should
//running
}
else
{
newdialog->displayerror();
layout->addWidget(error,3,0,2,2);
qDebug()<<"cud not connect";
}
}
If aclient->prework()==0 then a gui is displayed but how can i run aclient->receiveme() at this time as a thread so that it is continuously running and reading messages from socket.If a message is received,it should be displayed in the gui.
Without thread the gui would freeze.I tried to use QThread::movetothread() but i receive the following error
QThread::cannot move object with parent
and to use subclass method, client class must inherit QThread but since it is already inheriting QWidget,the following error is thrown
call to QObject is ambiguous
How can i use QThread here?
Widgets can run only within GUI thread, so you need to implement client as QObject subclass and communicate with UI via signal/slot connection. Qt wont allow you to do outputbox->append(a) in non UI thread (Supposing that outputbox is some QWidget here);
You probably don't even need to use threads here - Qt provides it's own socket classes with event (signal/slot) based API;
If you still need to use recv() in different thread, you need to subclass QThread (one approach) or QObject (another approach); In both cases you need to have signal like messageReceived(QByteArray) that will be connected to slot in your UI object that will handle message; So receiveme() slot might looks like:
void client::receiveme()
{
while(1){
if(recv(sockfd,receivebuf,1024,0)<0)
{
qDebug()<<errno;
break;
}
receivebuf[20]='\0';
QByteArray msg(receivebuf);
emit messageReceived(msg);
}
}
This article might help

Using QThread and moveToThread properly with QTimer and QTcpSocket

From reading this blog, this blog and some others, Subclassing QThread is bad practice. So I tried to apply this method.
But my problem is that I have a QTimer and a QTcpSocket in the class I want to move to a different thread. Suddenly, it's not as easy as it the examples used. :(
QThread m_commsThread;
m_pICommsHandler = new CommsHandlerIP();
m_pICommsHandler->moveToThread(&m_commsThread);
m_commsThread.start();
And here is the CommsHandlerIP class, methods are not included.
class CommsHandlerIP : public QObject
{
Q_OBJECT
public:
CommsHandlerIP();
~CommsHandlerIP(void);
protected:
QTcpSocket m_TCPSocket;
QTimer m_timer;
}
Issue is that the QTimer and the QTcpSocket (inside CommsHandlerIP class) are in the main thread even if you move CommsHandlerIP. So I can't start the timer or connect the socket.
If I try to moveToThread the QTimer and QTcpSocket (inside the constructor by passing the thread pointer for instance), this become really messy when I leave the app.
What should I do?
Class Instances are created on the calling thread.
QTimer inherits QObject.
Each Thread on Qt can have an event loop if it calls exec().
so you want to move QTimer to an event loop on another thread.
so you should manually move it.
Therefore, delay their creation until after you move the object: -
class CommsHandlerIP : public QObject
{
Q_OBJECT
public slots:
void Initialise();
private:
void Run();
// c++ 11, initialising in headers...
QTimer* m_pTimer = NULL;
QTcpSocket* m_pSocket = NULL;
};
void CommsHandlerIP::Initialise()
{
m_pTimer = new QTimer(this);
m_pSocket = new QTcpSocket(this);
Run();
}
QThread m_commsThread;
m_pICommsHandler = new CommsHandlerIP();
// Note Qt 5 connect style
connect(&m_commsThread, &QThread::started, m_pICommsHandler, &CommsHandlerIP::Initialise);
m_pICommsHandler->moveToThread(&m_commsThread);
m_commsThread.start();
When the thread is started, the CommsHanderIP Initialise function is called; this is where you should create and setup the QTcpSocket and QTimer objects before calling Run(). As the CommsHandlerIP is running in the new thread before creating those objects, they will also share the same thread affinity.
There is a much simpler method of achieving all this that follows the same algorithm but doesn't involve all the boilerplating needed to create threads and changing thread affinities, using QRunnable and QThreadPool
If I convert Merlin069's example, you'll see how it simplifies the code a bit:
class CommsHandlerIP : public QObject, public QRunnable
{
Q_OBJECT
public:
void run();
public slots:
//... any slots
signals:
//... any signals
private:
// c++ 11, initialising in headers...
QTimer* m_pTimer = NULL;
QTcpSocket* m_pSocket = NULL;
};
void CommsHandlerIP::run()
{
m_pTimer = new QTimer();
m_pSocket = new QTcpSocket();
//...
delete m_pTimer;
delete m_pSocket;
}
QThreadPool::globalInstance()->start(new CommsHandlerIP);
I stumbled across this when searching on Timer behaviour and movetoThread.
The accepted answer is a good work-around but not really the root cause of the problem. There is a general rule that when you move an object then all child objects will move as well. So you just need to make sure that the QTimer becomes a child so pass the this pointer in its constructor.
CommsHandlerIPL::CommsHandlerIP()
: QObject(), m_pTimer(new QTimer(this)) // <=== crucial to make it a "child" object
{
}

Create Thread in QDialog and emit signals to QDialog in Qt

I created an application that has a mainwindow and from this window creates a QDialog. This QDialog should create a RenderThread that emits received images from the camera or in the example emits text. When i debug this it seems that the connection is never made as adding a breakpoint in the slot CameraWindow::debugSomething does not get caught. Whats wrong ?
I followed this example: http://qt-project.org/doc/qt-4.8/threads-mandelbrot.html but it seems that i've done something wrong.
qtDEVC::qtDEVC(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
connect (ui.pushButton_startCam, SIGNAL( clicked() ),this,SLOT( startCam() ) );
/**Threading*/
CameraWindow camWindow = new CameraWindow(this);
}
int qtDEVC::startCam()
{
camWindow.show();
camWindow.startCaptureThread();
}
CameraWindow Class:
CameraWindow::CameraWindow(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
connect(&thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
}
void CameraWindow::debugSomething(std::string something){
QString somethings(something.c_str());
qDebug()<<somethings;
}
int CameraWindow::startCaptureThread(){
RenderThread *thread = new RenderThread(this, guid, CLEYE_COLOR_RAW, CLEYE_VGA, 50);
thread->StartCapture(); //starts thread in low priority and sets _running to true
}
CameraWindow header
class CameraWindow : public QDialog
{
Q_OBJECT
public:
CameraWindow(QWidget *parent = 0);
~CameraWindow();
Ui::CameraWindow ui;
public slots:
int startCaptureThread();
void debugSomething(QString);
private:
RenderThread thread;
};
RenderThread Class
void RenderThread::run()
{
// image capturing loop
while(_running)
{
qDebug()<<("render while()"); //is printed with qdebug correctly
if (restart)
break;
if (abort)
return;
qDebug("it"); //is also printed with qdebug correctly
emit sendText(text);
}
RenderThread header
class RenderThread : public QThread
{
Q_OBJECT
public:
RenderThread(QObject *parent, GUID cameraGUID, CLEyeCameraColorMode mode, CLEyeCameraResolution resolution, float fps);
RenderThread();
~RenderThread();
bool StartCapture();
signals:
void sendText(QString &text);
protected:
void run();
private:
QMutex mutex;
QWaitCondition condition;
//some more private variables for construction
};
I think that this creation seems somehow wrong: RenderThread *thread = new RenderThread(this);
The first thing that's worrying about the question is the word "RenderThread". Note that Qt only allows rendering on the main thread. You can create separate threads for calculations of image data, but whenever you use a painter and draw objects, that must happen on the main thread. However, If you're just going to capture the image and pass that to the main thread, via signals and slots, then that should be ok.
Secondly, whilst you've not shown all your code, I'm assuming from the function called RenderThread::run() and from the Qt example that you may have inherited from QThread here. If this is the case, please note that this is not how to use QThread. Instead, you should have your class inherit from QObject and move that to a QThread. You can read about how to use QThread properly here.
I know it's a Qt example that you've followed, but even the guys at Qt think it's a bad idea. Here's an article of how to really use QThreads.
With that in mind, here's an outline of how I would use QThread for this: -
class CameraWindow : public QDialog
{
private:
CameraObject* m_pCamObject;
};
class CameraObject : public QObject
{
Q_OBJECT
public:
private slots:
startCaptureThread();
private:
};
int CameraWindow::startCaptureThread()
{
m_pCamObject = new CameraObject;
QThread* pThread = new QThread;
this->moveToThread(pThread); // CameraObject will run on the new thread
connect(pThread, SIGNAL(started()), m_pCamObject, SLOT(startCaptureThread()));
connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater()); // clear up when
finished
pThread->start();
}
Note that here is a CameraObject, separated from the CameraWindow. The QThread is just a controller of the thread and keeps a clean separation from the CameraObject.
Another reason for handling threads this way is that you can move multiple QObject instances to the new thread, rather than always creating a new thread per object. If you've more threads than CPU cores, you're unlikely to gain by creating yet another thread.
In the constructor of CameraWindow class, you are connecting a RenderThread's signal but it is not the same object which is started in startCaptureThread. Change your startCaptureThread like this:
int CameraWindow::startCaptureThread()
{
thread.StartCapture(); //starts thread in low priority and sets _running to true
}
In this method, the thread member of CameraWindow is started.
P.S.: post the headers too, we can't see the members from this code.
In the mentioned example, CameraWindow class holds a RenderThread thread variable, not a RenderThread *thread.
You are connecting a pointer address in your connect call:
connect(&thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
Try to use a good address:
connect(thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
This is not a tested answer.