Many QPropertyAnimation instances VS single one? - c++

I use QPropertyAnimation simply as a source of ticks. I set 1 sec animation, infinite number of loops, call start() and then watch QElapsedTimer::elapsed() in a "tick handler" to know how much time is elapsed from animation start. So, i don't depend on loops count, animation start and stop values, and i don't care about property value that is being animated. Just a source of ticks!
Before that i was using QTimer that gives different results on Linux and Windows: for animation to be smooth in Linux, i had to use QTimer interval = 1000/30, but for windows 1000/60 was a minimum. So i had to use #ifndef, but that's a dirty code. In addition to that, QTimer uses signal-slot machinery, but QPropertyAnimation doesn't, so my QApplication event loop is not busy with animation events (am i correct?)
Now i need to animate N widgets (different kind of animation for each), and i am going to use QPropertyAnimation in the same way - as the same stupid source of ticks.
What is the CPU-cost difference between these variants:
N running QPropertyAnimation instances each connected to its own widget; Qt documentation say that QPropertyAnimation fire ticks at about 60fps = ~17 ms between ticks. But Qt cannot fire ticks from N different QPropertyAnimation instances simultaneously, because you may have started these animations in different time() - lets say there was 8 ms between QPropertyAnimation::start().
1 single running QPropertyAnimation instance connected to some kind of proxy object that transmit the ticks to N widgets; And all such widgets have a member 'animTick(void)' for that.

If all you want is a source of "ticks", then all you need is a QVariantAnimation, not even QPropertyAnimation.
The more animations, the higher the CPU cost. All you want is one animation, whose valueChanged(QVariant) signal is connected to multiple widgets.
Note that a QBasicTimer is not a source of anything, it's a very thin wrapper around the timer id returned by QObject::startTimer(). Thus it only works within a QObject instance, and only when you reimplement timerEvent(...).
The QVariantAnimation is simply a source of nicely timed ticks so that you don't need to reinvent the wheel.
If you want a general purpose timer that sends signals to multiple objects, you really want a QTimer. That's what it's for. That way you don't need proxy objects, as you can connect one signal to many slots. You can also connect a signal to a signal, if you so wish - thus you can forward or alias signals. A QTimer is simply a QObject with timerEvent(...) that emits a signal. That's all there's to it. It'd be silly to write your own.

Related

QBasicTimer interference with cuda

I had perfomances issues with CUDA in my program. The time taken for the same task (aligning clouds of 3D points) wasn't stable and could be 30 times higher sometimes.
I use Qt for the main interface, which initialize a thread with my worker class. The purpose of this class is to launch cuda computing on my data and to send Qt signals which will be captured by the GUI for updating the display of an OpenGl widget.
I had resolved my performances issues by removing a QBasicTimer in my OpenGL widget, it was used like this :
void SWGLCloudWidget::initializeGL()
{
// ...
m_oTimer->start(5, this);
}
It has no use at all, but i forget to delete it after some refactoring.
In Qt documentation it says :
The QBasicTimer class provides timer events for objects.
This is a fast, lightweight, and low-level class used by Qt internally. We recommend using the higher-level QTimer class rather than this class if you want to use timers in your >applications. Note that this timer is a repeating timer that will send subsequent timer events >unless the stop() function is called.
I was wondering how this low-level call could cause such a mess with CUDA, just for my curiosity.
The way I interpret:
As described in the documentation update()\updateGL()
does not cause an immediate repaint; instead it schedules a paint
event for processing when Qt returns to the main event loop. This
permits Qt to optimize for more speed and less flicker than a call to
repaint() does.
If for some reason (other threads, monitor refresh rate limitations,time spent computing new images, other signals and slots,etc...) the screen can be refreshed only every X milliseconds and you ask for a refresh rate of Y > X, then Qt will keep queuing paint events to the detriment of other events. Thus the system will be even less responsive as you observed.
This is an issue of congestion as it happens in network systems, where the throughput (average successful rate) is lower and lower than the requested rate.

Qt - Working with Threads

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.
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:
Qt 4.0 added rendering QImages from separate threads
Qt 4.4 added the ability to render text into images
Qt 4.8 added the ability to use QPainter in a separate thread to render to a QGLWidget, QGLPixelBuffer and QGLFrameBufferObject
Where Qt 4.4 introduced QFontDatabase::supportsThreadedFontRendering to check to see if font rendering was supported outside the GUI thread, in Qt5 this is considered obsolete and always returns true
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.

Does a signal or event exist for when a QGraphicsView or QWidget is done being painted or rendered?

I'm trying to time an application to see how long it takes to load up some information, and paint a graph. My function loads up the data first, then draws the graph.
The timing is fairly simple, it calls an external function that gets msecs since some date.
The problem is even if I set t1 in the beginning and t2 right after I call the draw function, t2 will return before the QGraphicsView is actually updated. (I know, it makes sense why this should be asynchronous)
For instance when I load a large file, it will return with 700 msecs after I subtract the two values, but the actual rendering doesn't finish until a few seconds later.
I've looked all over the web and scoured the Qt documentation. I can find tons of information on updating widgets yourself, but nothing on any kind of signal or event that is fired off after rendering finishes.
Even the QGraphicsScene::changed signal appears to only be fired off when the scene changes underneath, not when rendering is done and the user can SEE the changes.
Any help on how to do this?
Does a signal or event exist for when a QGraphicsView or QWidget is done being painted or rendered?
As far as I know, it does not exist. (looked for something similar)
user can SEE the changes
As far as I know, Qt uses double buffering, so if painting is finished, it doesn't mean that user can see the changes.
Any help on how to do this?
If you want to know when painting has finished, then...
You can subclass QGraphicsScene and implement your own drawItems, drawBackground or drawForeground. This is NOT simple (because item painting algorithm is complicated), but you'll be able to tell when every item has finished painted.
You can fire/emit signals from within paintEvent (QWidget-based classes) or paint() (QGraphicsItem/QGraphicsObject-based classes). You'll need to use your own classes, obviously, and you'll have to subclass either QGraphicsView, or items you're drawing within view, or QGraphicsScene.
You could also create proxy QPainter class, and this way you'll be able to know what exactly is being paitned and when.
Having said that I suspect you're approaching your problem incorrectly.
If you're only trying to draw a graph, then there's no reason for you to know when painting is finished.
If painting is finished, it doesn't mean user can see the result.
Paint events might be called more than once.
Recommended approach:
Receive/read the data (you're drawing in your graph) from external source using threads or timer events (you'll need to read it in small chunks if you're using timer events, obviously), then update the graph from time to time, and let Qt handle repainting.
How exactly does this allow me to detect the amount of time it takes from when I choose to open a file to when all the data is loaded and the graph is drawn and is visible?
You can detect when paintEvent has finished painting by subclassing whatever widget you're using to paint Graph, overriding paintEvent and firing signal from within paintEvent, calling a subroutine or doing whatever you want.
There is no warranty that paintEvent will be called only once.
To measure how slow individual routine is and locate bottlenecks, use profilers. VerySleepy, AQTime, and so on.
Instead of measuring how long it takes to load AND display data, it will make much more sense to measure separately loading time and display time. This is a GUI application, not a game engine, so you do not control precisely when something is being drawn.
I have not testet it, but I think by subclassing QGraphicsScene and reimplementing the render method you can measure the render time.
#include <QGraphicsScene>
#include <QTime>
class MyGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
void render ( QPainter * painter, const QRectF & target = QRectF(), const QRectF & source = QRectF(), Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio ) {
QTime t;
t.start();
QGraphicsScene::render (painter, target, source, aspectRatioMode);
qDebug("render time %d msec", t.elapsed());
}
};

Drawing from multiple threads in Qt

I'm writing a program in Qt, which runs 10 worker threads which calculate the trajectory of an object in space. They also have to draw the path of the object. I have a "Body" class deriving QGraphicsEllipseItem and it has a QPainterPath in it. The "Simulation" class takes a list of obstacles in the world, and the body to simulate and runs until the body collides with something. Simulation runs in a separate thread ( done with moveToThread, not by subclassing QThread). When the body collides, the Simulation emits a signal saying that it finished. When all threads have finished I'd like to draw the paths (I do it by invoking a method in "Body" which enables path drawing in its draw method).
Unfortunately I get ASSERT errors :
ASSERT: "!unindexedItems.contains(item)" in file graphicsview\qgraphicsscenebsptreeindex.cpp, line 364
They happen seemingly randomly. I've tried different connection types, to no result.
I'm starting the threads in a loop.
I'm using Qt 5.0
Generally speaking, with Qt you can't do any GUI operations outside of the GUI thread (i.e. the thread that is executing QApplication::exec(), which is typically the main() thread).
So if you have multiple threads manipulating QGraphicsItems (especially QGraphicsItems that are currently part of a QGraphicsScene), that is likely the cause of your assertion failures. That is, when the Qt GUI thread is doing its window refresh, it is reading data from the various QGraphicsItem objects as part of its calculations, and it expects the QGraphicsItems to remain constant for the duration of the refresh operation. If a QGraphicsItem is changed (by another thread) while the refresh routine is executing, then the calculations made by the main thread can become wrong/corrupted, and that occasionally causes an assertion failure (and/or other unwanted behaviors).
If you really need to use multiple threads, what you'll probably need to do is have the threads do all their calculations on their own private data structures that the Qt GUI thread has no access to. Then when the threads have computed their results, they should send the results back to the Qt GUI thread (via queued connection or QApplication::postEvent()). The GUI thread can then look at the results and use them to update the QGraphicsItems, etc; this will be "safe" because this update can't happen in the middle of a window update.
If that sounds like too much work, then you might consider just doing everything in the GUI thread; it will be much easier and simpler to make everything work reliably that way.
As mentioned by Jeremy, Qt rendering must be done on the main thread.
While you could move it all to the main thread, you've likely chosen to create separate ones for efficiency, especially as collision detection can be processor intensive. The best way to handle this is to split the modelling of the objects and their physics from their rendering, as you would in a Model / View / Controller pattern.
Create representations of the body instances that are not derived from any QGraphicsItem/Objects. These can then do their calculations on separate threads and have signals to graphics objects that are running in the main thread, which updates each body instance's graphic representation, allowing real-time rendering of the trajectories.

repeatedly render loop with Qt and OpenGL

I've made a project with Qt and OpenGL.
In Qt paintGL() was repeatedly call I beleive, so I was able to change values outside of that function and call update() so that it would paint a new image.
I also believe that it called initializeGL() as soon as you start up the program.
Now my question is:
I want that same functionality in a different program. I do not need to draw any images, etc. I just was wondering if there was a way to make a function like paintGL() that keeps being called so the application never closes. I tried just using a while(true) loop that kept my program running, but the GUI was inactive because of the while loop.
Any tips, other than threading preferably.
Thanks.
The exact mechanism will depend on which GUI toolkit you are using. In general, your app needs to service the run loop constantly for events to be dispatched. That is why your app was unresponsive when you had it running in a while loop.
If you need something repainted constantly, the easiest way is to create a timer when your window is created, and then in the timer even handler or callback, you invalidate your window which forces a repaint. Your paint handler can then be called at the frequency of your timer, such as 25 times per second.