Best way to update a QGraphicsScene after an item has been added
-
So, I have a qGraphicsView containing a QGraphicsScene. In this scene I initially have only two QGraphicsEllipseItems. I have then an algorithm that contonuously adds QGraphicsEllipseItems (points) to the scene and QGraphicsLineItems (lines) to the scene. This scene is displayed in a Dialog, with some buttons and EditText. I want the Dialog to stay responsive and the qGraphicsView to update each time an item has been added.
I currently use QCoreApplication::processEvent() to update each time I add or delete something, and it works perfectly.
I read that this method should not be used too much, only for tests, so, is there a better way to achieve this? I tried with QThreads, both by subclassing it and by using a class and moving that class to a thread. I made sure a signal is emitted each time a new element must be added to the scene (for example, I emit a signal with the coordinates of the new point or of the new line) and add it to the scene via scene->addEllipse/scene->addLine etc., but with QThreads the GUI is neither responsive nor it updates continuously, but in blocks. For instance, it updates the scene every second adding something like 1000 items in a single step.
So, I was wondering if I can continue to use that method (QCoreApplication::processEvents()) or if there are some better ways to achieve this.
Thank you in advance,
Michael -
Hi,
How many items do you plan to handle that way ?
-
@SGaist said:
Hi,
How many items do you plan to handle that way ?
At most one million, at least one thousand. In fact, the maximum number of node to be generated is a user choice, so... Anyway, I don't think I will go beyond 1 million (so, 1 million points + ~1 million lines at most). It really depends on the sizes of the scene too. Generating one million points and lines on a scene of 1000*1000 would cause the scene to be entirely black. Nonetheless, let's suppose 2 million items is the maximum number of items displayable on the scene.
-
If you want to see evolution of the scene your method will work just fine.
I do not think using QThread might helping you cause there is one long operations
in you code which has to be done in the main thread - update of the view.
Doing it for each item also means that adding item to the scene may be done in the main thread with the same result.The only real way to improve the speed is to disable view update and update it just once after all items are added.
The difference can be huge, but you will not see evolution. -
Thank you. In fact that was what I thought too, I was just worried, since I read that
processEvents()
[...] can cause a lot of unexpected issues if your code is not reentrant.
Here it says that it [...] makes the application react with delays to events. Furthermore the code is difficult to read and analyze, therefore this solution is only suited for short and simple problems that are to be processed in a single thread, such as splash screens and the monitoring of short operations. In response to this, I can say that, graphically speaking, the application works really well indeed, without delays (for example when I press a button to stop the execution).
Here it is said that you can call this function occasionally when your program is busy performing a long operation. But, in the event that you are running a local loop which calls this function continuously, without an event loop, the DeferredDelete events will not be processed. As far as I know, this is not my case, since I do have an event loop (I think) in the main.cpp, in which I havereturn a.exec();
:int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w(setUpParser(&a)); w.show(); return a.exec(); }