QEventLoop in showEvent() will trigger showEvent() twice!
-
hi guys:
win10 + 5.14.1, I has a problem , the showEvent() will trigger twice, in some condition the ui will be stuck, exec() will not return.here is my code:#define SHOWED 1 void MainWindow::showEvent(QShowEvent *e) { Q_UNUSED(e); qDebug("1enter showE"); #if SHOWED QEventLoop loop; QTimer timer; // connect(&timer,&QTimer::timeout,this,[&](){ qDebug("5time out"); loop.quit(); }); // QEventLoop:: connect(this,SIGNAL(sigTimerCallOut()),&loop,SLOT(quit())); QTimer::singleShot(0,this,[=](){ qDebug("3exec in timer"); emit sigTimerCallOut(); }); timer.setSingleShot(true); timer.start(3000); qDebug("2wait signal"); loop.exec(); #endif qDebug("4show End"); }
on the first time when app start ,it runs normal ,output:
1enter showE 2wait signal 3exec in timer 4show End
now I minimise and resotre the window , it shows:
1enter showE 2wait signal 3exec in timer 1enter showE 2wait signal 3exec in timer 4show End 4show End
after step by step debug after restoring window , at the first time it runs to :
qDebug("3exec in timer");
next it will emit the signal , but loop will not return and run at the begin of showEvent(), so
1enter showE
output again.
Why will happen like this? thanks. -
hi guys:
win10 + 5.14.1, I has a problem , the showEvent() will trigger twice, in some condition the ui will be stuck, exec() will not return.here is my code:#define SHOWED 1 void MainWindow::showEvent(QShowEvent *e) { Q_UNUSED(e); qDebug("1enter showE"); #if SHOWED QEventLoop loop; QTimer timer; // connect(&timer,&QTimer::timeout,this,[&](){ qDebug("5time out"); loop.quit(); }); // QEventLoop:: connect(this,SIGNAL(sigTimerCallOut()),&loop,SLOT(quit())); QTimer::singleShot(0,this,[=](){ qDebug("3exec in timer"); emit sigTimerCallOut(); }); timer.setSingleShot(true); timer.start(3000); qDebug("2wait signal"); loop.exec(); #endif qDebug("4show End"); }
on the first time when app start ,it runs normal ,output:
1enter showE 2wait signal 3exec in timer 4show End
now I minimise and resotre the window , it shows:
1enter showE 2wait signal 3exec in timer 1enter showE 2wait signal 3exec in timer 4show End 4show End
after step by step debug after restoring window , at the first time it runs to :
qDebug("3exec in timer");
next it will emit the signal , but loop will not return and run at the begin of showEvent(), so
1enter showE
output again.
Why will happen like this? thanks.@QtTester
I don't understand your question or what your issue is. You set off a singleshot timer first timeshowEvent()
is invoked and there you run aQEventLoop
. If during the 3 seconds waiting for the singleshot to fire a newshowEvent()
is raised you receive anothershowEvent()
then you will set off a new timer. The output shows what I would expect in such a situation.Calling
QEventLoop::exec()
inside a slot or event or waiting for a timeout like you do is not a good idea. I don't know what you are trying to achieve but there is doubtless a better way to accomplish it. -
@QtTester
I don't understand your question or what your issue is. You set off a singleshot timer first timeshowEvent()
is invoked and there you run aQEventLoop
. If during the 3 seconds waiting for the singleshot to fire a newshowEvent()
is raised you receive anothershowEvent()
then you will set off a new timer. The output shows what I would expect in such a situation.Calling
QEventLoop::exec()
inside a slot or event or waiting for a timeout like you do is not a good idea. I don't know what you are trying to achieve but there is doubtless a better way to accomplish it.@JonB thanks for reply.
as i said, after emit the signal ,the eventloop should quit.but it's NOT. and showEvent() call twice. and this is my question ,why showEvent() will be called twice? But at the first time app start, showEvent() run fine and not call twice!!!the Timer is for safe if we not emit the signal. after leave showEvent() , the timer will destruct and Will NOT CALL showEvent().
-
@JonB thanks for reply.
as i said, after emit the signal ,the eventloop should quit.but it's NOT. and showEvent() call twice. and this is my question ,why showEvent() will be called twice? But at the first time app start, showEvent() run fine and not call twice!!!the Timer is for safe if we not emit the signal. after leave showEvent() , the timer will destruct and Will NOT CALL showEvent().
@QtTester said in QEventLoop in showEvent() will trigger showEvent() twice!:
as i said, after emit the signal ,the eventloop should quit.but it's NOT
It does quit, as shown by your final 2 occurrences of
4show End
output. Maybe not at the time you expect, but it does.Rather than spend any more time on this, as I wrote earlier I suggest you get rid of
QEventLoop::exec()
and timers when you are inside an event. It's almost certainly not a good idea.why showEvent() will be called twice?
Because you minimize and maximize the window, or something like that? You can also examine
QShowEvent *e
to see whether they are spontaneous or not, might be significant. -
@QtTester
I don't understand your question or what your issue is. You set off a singleshot timer first timeshowEvent()
is invoked and there you run aQEventLoop
. If during the 3 seconds waiting for the singleshot to fire a newshowEvent()
is raised you receive anothershowEvent()
then you will set off a new timer. The output shows what I would expect in such a situation.Calling
QEventLoop::exec()
inside a slot or event or waiting for a timeout like you do is not a good idea. I don't know what you are trying to achieve but there is doubtless a better way to accomplish it. -
no , every time you restore the window the showEvent() will call twice(), I cannot explain why. if set SHOWED=0 showEvent() will call just one time! strange!
You must not spin an event loop inside an event.
-
You must not spin an event loop inside an event.
@Christian-Ehrlicher
Thank you for chiming in to resolve! I was trying to tell the OP it was "a bad idea" to do it from an event and not to bother analyzing it further, but this makes it even simpler if you are not even allowed to do it :) -
-
You must not spin an event loop inside an event.
@Christian-Ehrlicher
it's because i have to call a function in showEvent() , and the function also will be call in a thread. that's why i need a eventloop to wait a signal.
Now i change it like this: check the thread owner first, if it's in the ui thread, it will not use eventloop. -
@Christian-Ehrlicher
it's because i have to call a function in showEvent() , and the function also will be call in a thread. that's why i need a eventloop to wait a signal.
Now i change it like this: check the thread owner first, if it's in the ui thread, it will not use eventloop. -
@Christian-Ehrlicher
it's because i have to call a function in showEvent() , and the function also will be call in a thread. that's why i need a eventloop to wait a signal.
Now i change it like this: check the thread owner first, if it's in the ui thread, it will not use eventloop.@QtTester said in QEventLoop in showEvent() will trigger showEvent() twice!:
that's why i need a eventloop to wait a signal.
But why do you need to wait, especially from within an event handler, that is the question? Suppose the wait takes 5 minutes? Suppose the thread fails to emit the signal, for whatever reason?
You would be expected to set off the thread function, exit the event, and then do whatever elsewhere as & when the thread function ends or send its signal. That is what event-driven programming paradigm is about.