Pregunta

i using qt5 and opencv to create an application that give a user inteface using qt and does the image processing part in opencv.....

so far my design is:

  1. i am displaying a video and some standard controls like buttons and checkboxes using qt main gui thread
  2. for capturing image and processing it, i have created a worker class derived from QObject and moved it to a thread....
  3. the function that is executed in the worker class(Worker::process) has a blocking while loop.....that constantly:
    • captures a frame from a video or a camera
    • does some processing on it
    • converts from cv::Mat to QImage
    • emit a signal to the main thread to display the QImage
  4. also in order to recieve user input i was using emitting signal from the main thread to the worker slots

the problem i faced was that the signal from the main thread never got picked off by the worker because of the event loop blocking while loop.

after much searching i came up with the solution to use Qt::DirectConnection argument while connecting the signal from the main thread to the worker slots. that solved the problem at that time.

now i need to add a qtimer or qbasictimer inside the blocking while loop....and guess what, the timer slot(in the case of qtimer) and the protected timerEvent handler (in the case of the qbasictimer) never get called. my hunch is that again the blocking while loop is the culprit

after much searching and reading on forums i have come to the conclusion that somehow my over all design maybe incorrect.....and as i keep adding more functionality to my application these problems will keep showing up.

I have two options now:

  1. somehow call the threads exec() function inside the blocking while loop. so the question to the gurus out there is: "how do i call the thread::exec() method inside a worker QObject class, i need the reference to the thread running the worker to call exec()" (short term solution)

  2. change the whole implementation.....and here the questions is: "what are my options....." (long term)

please feel free to ask for details in case my wording or english has made the problem unclear in any way.....thanks...

¿Fue útil?

Solución

Inside your worker's blocking loop, call qApp->processEvents(); periodically.

http://qt-project.org/doc/qt-5.1/qtcore/qcoreapplication.html#processEvents

#include <QApplication>
// ...
void Worker::doWork()
{
    while(true)
    {
        someLongImageProcessingFunction();
        qApp->processEvents();
    }
}

This should allow for the slots to get processed, and for the timers to update.

Using a direct connection may let you access and change values local to your worker, but you should be careful about thread safety. If you put a QMutexLocker right before your values that get modified by your GUI and right before your worker thread uses them, you should be good.

http://qt-project.org/doc/qt-5.1/qtcore/qmutexlocker.html

Also if you wanted any of those slots to run on the worker thread, you need to use the QueuedConnection.

http://qt-project.org/doc/qt-5.1/qtcore/threads.html

http://qt-project.org/doc/qt-5.1/qtcore/qthread.html#details

In some parts of the Qt docs it describes subclassing the QThread class. Other parts recommend the Worker/Producer model, and just use connections to setup how you use your threads. Usually there are fewer gotchas with the Worker/Producer model.

Hope that helps.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top