Question about show() hide()
-
@JonB
I know it will block the main thread. In another real project of mine, I also displayed multiple sub-widgets one by one, and then showed the parent widget. After that, I hid another parent widget, but the actual display sometimes showed 27 out of 30 images simultaneously, with the remaining three images appearing one by one. However, there were times when all 30 images would display together. I initially thought it was due to the time needed for painting high-resolution images in my paint event, so I used a for loop to simulate this time-consuming process. It takes about 10ms to paint each image. In the demo, even with a 1s delay, it does not result in displaying the images one by one; instead, all images are shown simultaneously after the paint event for each image completes.What I primarily want to know is whether there are any factors that could affect the order of display. I have been unable to identify the issue in my actual project.
-
@JonB
I know it will block the main thread. In another real project of mine, I also displayed multiple sub-widgets one by one, and then showed the parent widget. After that, I hid another parent widget, but the actual display sometimes showed 27 out of 30 images simultaneously, with the remaining three images appearing one by one. However, there were times when all 30 images would display together. I initially thought it was due to the time needed for painting high-resolution images in my paint event, so I used a for loop to simulate this time-consuming process. It takes about 10ms to paint each image. In the demo, even with a 1s delay, it does not result in displaying the images one by one; instead, all images are shown simultaneously after the paint event for each image completes.What I primarily want to know is whether there are any factors that could affect the order of display. I have been unable to identify the issue in my actual project.
@Quiccz I guess paint events(in event loop) may not come one after another in a big app with a lot of running threads. And threads also access CPU randomly one after another. The main thread has some pause as well. Some other apps in the OS need to access CPU too.
-
@JonB
I know it will block the main thread. In another real project of mine, I also displayed multiple sub-widgets one by one, and then showed the parent widget. After that, I hid another parent widget, but the actual display sometimes showed 27 out of 30 images simultaneously, with the remaining three images appearing one by one. However, there were times when all 30 images would display together. I initially thought it was due to the time needed for painting high-resolution images in my paint event, so I used a for loop to simulate this time-consuming process. It takes about 10ms to paint each image. In the demo, even with a 1s delay, it does not result in displaying the images one by one; instead, all images are shown simultaneously after the paint event for each image completes.What I primarily want to know is whether there are any factors that could affect the order of display. I have been unable to identify the issue in my actual project.
-
My understanding of the event loop is that, after executing a.exec() in the main function, the program enters the event loop. Other threads can emit messages (such as when a QTimer's time is up), which will place the corresponding functions into the event loop. The event loop acts like a queue, where events are retrieved from the front of the queue and their corresponding functions are executed until each function is completed before moving to the next event.
If that's the case, why do we see w1.showall, w1.show, followed by pic show event, then parent show event, and finally w2.hideall and w2.hide? It appears that the show event doesn't enter the event loop but is instead a regular function call because it is invoked before w2.hide within my QTimer function.
In this scenario, the reason pic show event comes first is that after calling w1.showall, it realizes that the parent widget (w1) is not yet shown, so it doesn't trigger the show event. After w1 is shown, it doesn't immediately trigger w1's show event. Instead, it needs to iterate through the child widgets and invoke their show event if they are in the shown state.
-
If i let w1 show first and add delay in paintevent and paint 11 pics and add repaint https://streamable.com/r8r0u9
if i let w1.showall first https://streamable.com/izhzvq
-
If i let w1 show first and add delay in paintevent and paint 11 pics and add repaint https://streamable.com/r8r0u9
if i let w1.showall first https://streamable.com/izhzvq
The reason for this is the parent-child struture.
If you show the Parent first and then showAll childs (pics) in a loop, it works as in the first video.If you call showAll first, all pics/childs are queued to be shown, but cant show up because their parent is hidden. When you then show the ParentWidget the queue is emptied and all childs show up without delay.
That would be my explanation for this. Could also have other influences
-
The reason for this is the parent-child struture.
If you show the Parent first and then showAll childs (pics) in a loop, it works as in the first video.If you call showAll first, all pics/childs are queued to be shown, but cant show up because their parent is hidden. When you then show the ParentWidget the queue is emptied and all childs show up without delay.
That would be my explanation for this. Could also have other influences
-
-
There is no reason to call
show()
orhide()
on your pictures. Just show and hide the parent widgets.Here is my try to explain why with the order
show()
->showAll()
the pictures can appear one after the other. You are correct that the basic understanding of signals and slots is that events are queued inside the event loop. However, the default connection is an AutoConnection. If both sender and receiver are inside the same thread this defaults to a DirectConnection. This means that the event loop is skipped. This is especially true forrepaint()
which will immediately draw the widget. Because you are doing this in a loop (and PicWidget::paintEvent() has a delay) one picture must appear after the other. The general advice is to never userepaint()
, but useupdate()
instead. This can significantly increase performance.update()
will gather several calls first if they appear quickly after another and only then call repaint(). I am not entirely sure about the underlying mechanism of update() or if the event loop is involved.show()
itself will callupdate()
(or something similar) internally. This means that several calls to show() also are first gathered.With the order
showAll()
->show()
nothing will happen when calling show() for each picture because their parent widget is not visible. They are basically marked as visible and that's it. I don't think repaint() will do anything here as well. Only whenshow()
is called on the parent will all the pictures be drawn. As this is a single paintEvent on the parent widget it will not be interrupted (drawing all of its children) before it can be shown on the screen (Qt does not paint on the screen directly, but uses double buffering, so that only after all draw commands of a single update() call are finished will they show on the screen). Just as I said in the beginning: Don't ever call show/hide on your PicWidgets. Just call it on the parent which will manage all the rest.@Quiccz said in Question about show() hide():
I found my program bug. so close it
This is up to you. If you found a particular answer useful, click the three dots of that answer and mark the post as solved. Otherwise post your solution for others to find and select that one as the correct answer. (Somewhere there is also an option to mark it as solved without selecting an answer.)
-
There is no reason to call
show()
orhide()
on your pictures. Just show and hide the parent widgets.Here is my try to explain why with the order
show()
->showAll()
the pictures can appear one after the other. You are correct that the basic understanding of signals and slots is that events are queued inside the event loop. However, the default connection is an AutoConnection. If both sender and receiver are inside the same thread this defaults to a DirectConnection. This means that the event loop is skipped. This is especially true forrepaint()
which will immediately draw the widget. Because you are doing this in a loop (and PicWidget::paintEvent() has a delay) one picture must appear after the other. The general advice is to never userepaint()
, but useupdate()
instead. This can significantly increase performance.update()
will gather several calls first if they appear quickly after another and only then call repaint(). I am not entirely sure about the underlying mechanism of update() or if the event loop is involved.show()
itself will callupdate()
(or something similar) internally. This means that several calls to show() also are first gathered.With the order
showAll()
->show()
nothing will happen when calling show() for each picture because their parent widget is not visible. They are basically marked as visible and that's it. I don't think repaint() will do anything here as well. Only whenshow()
is called on the parent will all the pictures be drawn. As this is a single paintEvent on the parent widget it will not be interrupted (drawing all of its children) before it can be shown on the screen (Qt does not paint on the screen directly, but uses double buffering, so that only after all draw commands of a single update() call are finished will they show on the screen). Just as I said in the beginning: Don't ever call show/hide on your PicWidgets. Just call it on the parent which will manage all the rest.@Quiccz said in Question about show() hide():
I found my program bug. so close it
This is up to you. If you found a particular answer useful, click the three dots of that answer and mark the post as solved. Otherwise post your solution for others to find and select that one as the correct answer. (Somewhere there is also an option to mark it as solved without selecting an answer.)
@SimonSchroeder The reason I use show ()/hide() for pics is that in my actual project, each picture has a different display duration. For example, if there are three pictures in total, initially they are all displayed. After 1 second, the first picture is hidden. After 2 seconds, the second picture is hidden. After 3 seconds, the third picture is hidden, and then it switches to the next set of pictures.
-
-