QThread or std::thread?
-
Hello Qt community,
I was wondering which type of thread I should use for my project. The main thread would be processing the Qt loop, and the other threads would basically update variables and such (Positions, QPixmaps, etc.)
Is there an important difference(s) I should be aware of?
std::thread
sounds much easier to use... -
If you are going to communicate using signals and slots (what you should) than you need QThread.
-
Oh, is it as simple as that? Because I think I'm not going to use signals and slots.
-
@Pippin How are you going to report to the main event loop, that the position, or pixmap changed? Or if you will use QRunnable than you are back with signal/slots. I would stick with QThread since it makes things easier and more compact. You can also start another eventloop in next thread and let computing running there. See http://thesmithfam.org/blog/2010/02/07/talking-to-qt-threads/
-
Well everything that the other threads would be updating are QGraphicsItems that would be displayed inside a QGraphicsView. I was going to disable the automatic update of the Viewport
myView.setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
then update it whenever necessary:
myView.update();
Is it okay?
-
@Pippin
never mix Qt event loop with std::threads. it just doesn't work together.
Qt has all the async functions you need, similar syntax to std. -
@Pippin said:
Well everything that the other threads would be updating are QGraphicsItems that would be displayed inside a QGraphicsView. I was going to disable the automatic update of the Viewport
myView.setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
then update it whenever necessary:
myView.update();
Is it okay?
All GUI-related classes must be used in the GUI thread only. (The GUI thread is the one which created the QApplication.) You cannot use them in other threads.
-
@JKSH Not sure what you're telling me: are you telling me that I must use QThreads, or are you telling me that even QThreads won't let me modify other QObjects?
-
@Pippin said:
@JKSH Not sure what you're telling me: are you telling me that I must use QThreads, or are you telling me that even QThreads won't let me modify other QObjects?
I mean you cannot create QGraphicsView/GraphicsItem/QPixmap in another thread, and you cannot call those class' methods in another thread. This rule applies regardless of whether you use QThread or std::thread.
Anyway, the Graphics View Framework is designed to handle lots of items at the same time. Perhaps you don't need threads at all?
-
@JKSH Oh wow, I wasn't aware of this. That sounds very problematic. Also, why is this not mentioned in pages like http://doc.qt.io/qt-5/qtconcurrentrun.html ?
The thing is, my project displays moving cards (QPixmaps) inside a QGraphicsScene/QGraphicsView instance, and I must control the FPS rate so that cards are always moving at the same speed. The (basic) idea is to slightly move 1 or more card(s), then update the QGraphicsView, then sleep, then slightly move 1 or more card(s) again, etc. at a given, fixed FPS rate so that the moving always looks natural. This is why I need another thread that computes the new positions, then update the view (so that the main thread draws it), then sleep, then repeat.
How can I do that?
-
@Pippin said:
I must control the FPS rate so that cards are always moving at the same speed. The (basic) idea is to slightly move 1 or more card(s), then update the QGraphicsView, then sleep, then slightly move 1 or more card(s) again, etc. at a given, fixed FPS rate so that the moving always looks natural. This is why I need another thread that computes the new positions, then update the view (so that the main thread draws it), then sleep, then repeat.
How can I do that?
Have a look at the animations framework: http://doc.qt.io/qt-5/animation-overview.html You don't need to calculate every frame yourself
-
-
@JKSH I've just used QtConcurrent to launch a function that makes a window visible and changes the background of a QGraphicsView, and there was no problem. I don't understand, because according to you my attempt should have failed. What am I missing?
Also, the following code can't seem to work:
QThreadPool *pool; QFuture<void> future = QtConcurrent::run(pool, foo2);
where
foo2
is a void function without arguments. The compilation report is quite long and can be found here: http://pastebin.com/Sq35HD0vI don't understand how I'm not using
QtConcurrent::run()
correctly. However the following code works:QFuture<void> future = QtConcurrent::run(foo2);
If someone sees the catch, feel free to point it out. Thanks.
-
@Pippin said:
@JKSH I've just used QtConcurrent to launch a function that makes a window visible and changes the background of a QGraphicsView, and there was no problem. I don't understand, because according to you my attempt should have failed. What am I missing?
The thing is, it's not guaranteed to fail immediately. Manipulating GUI classes in a different thread leads to undefined behaviour. That means, sometimes it might work as you'd expect, but it might crash at other times.
See the documentation: "Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread."
Also, the following code can't seem to work:
QThreadPool *pool; QFuture<void> future = QtConcurrent::run(pool, foo2);
where
foo2
is a void function without arguments. The compilation report is quite long and can be found here: http://pastebin.com/Sq35HD0vThat overload of QtConcurrent::run() was introduced in Qt 5.4.0: http://code.qt.io/cgit/qt/qtbase.git/tree/dist/changes-5.4.0 (so it won't compile with older versions of Qt)
-
@Pippin
This cannot work:QThreadPool *pool; QFuture<void> future = QtConcurrent::run(pool, foo2);
You did not create an instance of QThreadPool.
-