As you mentioned about the great article How to Really Use QThread , start by explaining code that you are not sure about breaking it.
QThread* thread = new QThread; Worker* worker = new Worker(); worker->moveToThread(thread); connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString))); connect(thread, SIGNAL(started()), worker, SLOT(process())); connect(worker, SIGNAL(finished()), thread, SLOT(quit())); connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start();
This code is usually placed in an object in the main thread, possibly in MainWindow: -
Create a new thread object - QThread is actually more of a thread controller than a thread
QThread* thread = new QThread;
Create a new work object. This is an object that will work in another thread. Since this can be moved to another stream, note that you can create multiple objects and move them to the same stream.
Worker* worker = new Worker();
Move the object and its children to a new stream
worker->moveToThread(thread);
Set up useful connections for monitoring and managing your work. Let's start with any mistakes, so we know if the worker had a problem
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
To begin processing the worker’s object, we connect the initial () stream signal to the worker’s process () slot. In your example, the process will be a modifySaturation slot
connect(thread, SIGNAL(started()), worker, SLOT(process()));
When the worker finishes processing, if this is the only object, he needs to exit and clear, so the thread must exit
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
To tidy up, now both the worker and the stream are no longer needed, make sure they are cleaned after themselves
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
Finally, let us go to the thread-> start () call, which initiates the initial start () signal that we previously connected to the worker process () function
thread->start();
With all this in mind, let me solve the questions posed: -
1 How can I reuse this thread for several methods (changing saturation, changing brightness, changing hue ...), I need to create a new stream for every other task (it seems a little more complicated)?
No, you do not need a new thread for each method. You can either use the current object or expand it to do all the processing, manage it through signals and slots from the main thread, or you could create a separate object for each method and move all of them to a new thread.
If you are using multiple objects that have been moved to a new thread, make sure that you have not connected a completed object () signal to call quit () on the stream if other objects are still using this stream. However, you still need to clear the objects and the stream when you are done with them.
2 Why does a join statement require so many lines to execute a single process? those. in my case, I have a slider for changing the saturation of the image in QGraphicsView, I want to create a stream for processing manipulations with image pixels, and then return the formatted QPixmap to my GUI and start the rendering method to draw a new image on the canvas (I don’t think that can I update my canvas from my stream?)
The general rule is that you can only update graphic objects (widgets, graphic elements, etc.) from the main stream. (There is an exception, but it is beyond the scope of this discussion and does not matter here.)
When using only one object from several connection signals, three are used to delete objects upon completion, one for processing error messages and final connection ensures that the work object starts from the beginning of the stream.
Nothing prevents you from changing this by creating your stream and first starting it, creating work objects, connecting the corresponding signals and then moving them to the stream, but you need to get workers to start doing something, for example, processing saturation as soon as they are transferred to new stream.
QThread* pThread = new QThread; pThread->start(); Worker* worker1 = new Worker(); Worker* worker2 = new Worker(); Worker* worker3 = new Worker(); worker1->moveToThread(pThread); worker2->moveToThread(pThread); worker3->moveToThread(pThread);
Work objects are moved here to a new thread that is running. However, work objects are inactive. Without a connection, we can call the slot that needs to be called. Suppose a process slot accepts an integer parameter ...
QMetaObject::invokeMethod( worker1, "process", Q_ARG( int, param ) ); QMetaObject::invokeMethod( worker2, "process", Q_ARG( int, param ) ); QMetaObject::invokeMethod( worker3, "process", Q_ARG( int, param ) );
So, as you see here, you do not always need to connect the signals, but it is convenient.