0

I have a QTimer for executing OpenCV code and changing an image in a QLabel every 20 milliseconds, but I want to run this OpenCV code more naturally and not depend on the timer.

Instead, I want to have one main thread that deals with user input and another thread that process images with OpenCV, what I can't find is a thread safe way to change the QLabel image (pixmap) in one thread from another thread, could someone describe this process, maybe give some code examples? I also want to know the pros and cons of using QThread, since it's plataform free, it sounds to be user level thread and not a system level which usually runs smoother.

Michel Feinstein
  • 13,416
  • 16
  • 91
  • 173
  • You can send signals from your working thread to the main thread that will update the label's content. – vahancho Nov 05 '13 at 22:42
  • @vahancho could you please give me some examples or links? – Michel Feinstein Nov 05 '13 at 22:44
  • If I recall correctly updating the UI from a separate thread than where it's created does not work well under Qt. signals and slots are a safe way to communicate between threads though. – Jay Nov 05 '13 at 23:11
  • A good starting place for using QThread is to read this article: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ – TheDarkKnight Nov 06 '13 at 08:54

1 Answers1

0

You can only instantiate and work with QPixmap on the main (GUI) thread of your application (e.g. what is returned by QApplication::instance()->thread())

That's not to say you can't work with a QPainter and graphics objects on other threads. Most things work, with exceptions guided by constraints imposed by the OS.

Successive versions of Qt have managed to find ways to support things that previously didn't work. For instance:

Note: you shouldn't hold your breath for the day that Qt adds support to work with QPixmap on non-GUI threads. The reason they exist is to engage the graphics layer directly; and finding a way to work around it just so you could use something named QPixmap wouldn't do any good, as at that point you'd just be using something equivalent to what already exists as QBitmap.

So all that has to do with the ability to instantiate graphics objects like QFont and QImage on another thread, and use them in QPainter calls to generate a graphical image. But that image can't be tied directly to an active part of the display...you'll always be drawing into some off-screen buffer. It will have to be safely passed back to the main thread...which is the gateway that all the direct-to-widget drawing and mouse events and such must pass through.

A well known example of how one might do this is Qt's Mandelbrot Sample; and I'd suggest getting started with that... making sure you understand it completely.

Note: For a different spin on technique, you might be interested to look at my Thinker-Qt re-imagining of that same sample.

  • I will take a look into Mandelbrot Sample, it looks like it has everything I need in there, so far I can see the answer lies in sending signals for an update...thanks! – Michel Feinstein Nov 06 '13 at 01:54
  • looking into the Mandelbrot Sample, they declare the Signal as signals: void renderedImage(const QImage &image, double scaleFactor); what's the benefit of the 'const' and why it's &image instead of *image as function usually are defined for pointers parameters? – Michel Feinstein Dec 26 '13 at 03:37
  • @mFeinstein Bear in mind that in the signal/slot design, a signal may be connected to multiple slots. If the image weren't declared as const then what if there were multiple slots that ran? You'd wind up with this ordering problem of modification. The "principle of least privileges" guides that kind of decision. As for why use references instead of pointers, one practical difference is that you are saying that it is required and never null. I myself only use raw pointers in places where nullptr is an allowed or expected legal input. There's other reasons: research "why use references". – HostileFork says dont trust SE Dec 26 '13 at 12:32
  • I just got confused because I never saw this kind of function signature. Every function I ever saw that had a pointer as an input will be like void foo(* input) so I am not sure what void foo(&input) means and it's behavior – Michel Feinstein Dec 26 '13 at 17:45
  • @mFeinstein As I said, research into what references are. They are a C++ thing, not present in C. – HostileFork says dont trust SE Dec 26 '13 at 19:36
  • I just understood there is something called references in C++ haha ok, time for research! – Michel Feinstein Dec 26 '13 at 22:00
  • now I am more used with Qt, but one thing I still am not sure...if I am passing all this images as references, what prevents the memmory leak? – Michel Feinstein Mar 19 '14 at 03:24
  • @mFeinstein I hadn't myself really internalized that it was the case *(at least, not lately)*...but rather specifically with the Signal/Slot mechanism, if it's cross-thread and you pass in a reference to a type it knows, [it makes a copy of it](http://stackoverflow.com/a/18146433/211160) to use for the duration of the slot call. There should be better documentation of that fact. The copy will often be cheap for things like QImage, though, because it is an [implicitly shared type](http://qt-project.org/doc/qt-5.1/qtcore/implicit-sharing.html). It would be broken if it didn't copy-you're right. – HostileFork says dont trust SE Mar 19 '14 at 03:50
  • I see, so it will copy and delete when all the slots are executed...makes sense! – Michel Feinstein Mar 19 '14 at 16:55