Display Image Processing Results in Qt UI

What is the best way to display results (e.g. position of a detected object) that have been calculated in the DoImageProcessing() Method (SingleStreamHandler/MultiStreamHandler class) in a Qt UI?

My current approach is to create two objects: the 1st object’s class camerahandler has been derived from SingleStreamHandler and 2nd objects class mainwindow derived has been derived from QWidget. The camerahandler holds a pointer of the mainwindow object. Everytime DoImageProcessing() calculates new results the camerahandler uses this pointer to call a function of the mainwindow object that updates the content of a QLabel or QGraphicsTextItem in order displays the results. Methods like setText() or setPlainText() will be used with QLabel and QGraphicsTextItem. With QLabel everything works fine. But with QGraphicsTextItem the following Error occurs while running the program:

QObject: Cannot create children for a parent that is in a different thread.emphasized text

1 Like

Hi @gerd

before I give you a solution it is probably best to look at what is causing the error message.

When reimplementing

DoImageProcessing()

all your processing runs in a separate thread different from your applications main or UI thread. So if you want to display some results after calculating them in this method you will need some kind of synchronisation. Otherwise you will call into the UI thread from different thread, which requires thread safety. Unfortunately:

QObject and all of its subclasses are not thread-safe. This includes the entire event delivery system. It is important to keep in mind that the event loop may be delivering events to your QObject subclass while you are accessing the object from another thread.

see here:

https://doc.qt.io/qt-5/threads-qobject.html

So with QLabel things only seem to work as setText() does not do any checks. However, setPlainText() is more complicated and creates a QObject which is aware of the diffident threads.

Luckily Qt’s documentation also provides a solution that does not require manual synchronisation (which is of course always an option)

You can manually post events to any object in any thread at any time using the thread-safe function QCoreApplication::postEvent(). The events will automatically be dispatched by the event loop of the thread where the object was created.

If you need an example on how to implement that, have look at:

ImageView::Refresh()

It actually posts a custom event to main event loop to handle drawing and also uses (depending on your configuration) a condition variable to synchronise drawing with calling thread (which should not be required in your case).

For completeness let me add, that Qt’s signal and slots mechanism usually also does the trick and is easy to use. However it is currently quite difficult to use with the acquisition handler classes. I plan to add easy access soon.

1 Like

As announced, I have now added to virtual methods to the stream handlers that allow users to allocate and deallocate resources within the acquisition thread.

Now you might ask, how does this help with Qt’s signals and slots?
Sending or receiving signals requires you to subclass QObject. As written above QObject is aware of its thread affinity. So in order to send a signal from the acquisition thread to the UI thread you need a QObject living in the acquisition thread!
Now you can create one in StreamHandler::Begin() and delete it in StreamHandler::End()

2 Likes

Hello @Andreas,

the approach you have suggested based on signals and slots and the update of the stream handlers works as expected.
I created a QObject inside the acquisition thread and connected it to the QWidget object of the UI thread.
Now I can call methods like setPlainText() to update the displayed text of an QGraphicsTextItem without receiving an error.
Thank you :smile: