PDA

View Full Version : Terminating process after closing QWidget



Binary91
6th July 2015, 21:59
Hi,

I have a single QWidget that is defined and showed in the process' main function, like this:

// main.cpp

#include "main.h"

int main(int argc, char *argv[])
{
QApplication application(argc, argv);
clsWindowMain windowMain();
windowMain.showMaximized();

int ret = application.exec();

delete(settings);
return ret;
}

When I run the program and close the QWidget by mouse click, the whole process terminates.

BUT: When I create a button that should manually close the QWidget like this:

void clsWindowMain::slotButtonClicked()
{
this->close();
}
... then the QWidget also closes, but the process is still working in background. I can see it when I open the process manager in windows and I can see it when I try to re-run the program...

Does anybody have a clue why it is not working?

Thank you in anticipation!

ChrisW67
6th July 2015, 22:24
We cannot see the code that does any processing so it would be hard to tell you why your processing code does not stop.

Binary91
7th July 2015, 00:14
Hi Chris,

you are right. The problem was that my code is really large and I don't know where the problem is so I would have to post all code with all files. I think I'd never get an answer this way...

Well, I found the problem. What I did not tell you is, that I subclassed QWidget's show-function and called a QDialog in it, this way:

void clsWindowMain::show()
{
QWidget::show();
if(!this->windowInstall->isInstalled())
{
this->windowInstall->exec();
if(!this->windowInstall->isInstalled())
this->close();
}
}
I'd like to let QWidget check whether my program is already installed on the computer or not. If not, then QWidget should automatically call a QDialog that holds all installation settings.
The problem with it is, that the main event loop has never started (application.exec()), because QDialog has its own event loop and even when I close the QWidget after QDialog terminated, it will return to main function and start the main event loop.

The problem is, that I can't see a good way to prevent this. How can I create the main QWidget + starting its event loop (application.exec()) and after that automatically checking for installation status? As soon as I start the event loop, I can't do anything till event loop returns...

int main(int argc, char *argv[])
{
QApplication application(argc, argv);

clsWindowMain windowMain(settings);
windowMain.show();
int ret = application.exec();

if(!windowMain.windowInstall->isInstalled()) // <-- will not work because main function stops and waits at application.exec() till windowMain is closed...
windowMain.windowInstall->exec();

return ret;
}

My only solution is something like that:

int main(int argc, char *argv[])
{
QApplication application(argc, argv);

clsWindowMain windowMain(settings);
windowMain.show();
windowMain.windowInstall->exec();
int ret;
if(windowMain.windowInstall->isInstalled())
ret = application.exec();

return ret;
}
But I think this method is dirty. I'd like to manage that stuff with methods of windowMain and not manually from the main function...

How can I show windowMain, start its event loop (application.exec()) and automatically let it check for installation?

anda_skoa
7th July 2015, 00:27
You call the check method after the event loop is running.
See QTimer::singleShot()

Cheers,
_

Binary91
7th July 2015, 10:34
You call the check method after the event loop is running.
See QTimer::singleShot()Ahh there we go! Thank you for that hint, it works great!

There is only one final question left. I do it now like this:

int main(int argc, char *argv[])
{
QApplication application(argc, argv);
clsWindowMain windowMain();

QTimer::singleShot(2000, &windowMain, SLOT(slotApplicationStart()));
int ret = application.exec();

return ret;
}

void clsWindowMain::slotApplicationStart()
{
this->showMaximized();
if(!this->windowInstall->isInstalled())
{
this->windowInstall->exec();
if(!this->windowInstall->isInstalled())
this->close();
}
}

It works, but now I'd like to shorten the time (msec) as much as possible, but I'm afraid of waiting not long enough for application.exec() to finish, so I have the same problem again --> QTimer starts the event loop of QDialog before the main event loop starts...
What do you think? Is there a way to detect how long application.exec() needs to get started?

EDIT:
I realized that even setting QTimer's msec to 1msec does what I wanted... Why this? Does QTimer start multithreading so two event loops can start simultaneously?
I mean, where is the difference between these to ways:

int main(int argc, char *argv[])
{
QApplication application(argc, argv);
clsWindowMain windowMain();

QTimer::singleShot(1, &windowMain, SLOT(slotApplicationStart()));
int ret = application.exec();

return ret;
}


int main(int argc, char *argv[])
{
QApplication application(argc, argv);
clsWindowMain windowMain();

windowMain.slotApplicationStart();
int ret = application.exec();

return ret;
}
The second one fails (logically, because the main event loop did not start)..
So QTimer starts multithreading??

Lesiok
7th July 2015, 10:44
Just use time = 0 ms.
QTimer::singleShot(0, &windowMain, SLOT(slotApplicationStart()));
or use QMetaObject::invokeMethod method.

jefftee
7th July 2015, 10:45
You can use 0 as the interval for the singleShot timer, which will cause the timer to fire as soon as the event loop is running and processed other events that may be pending. i.e. The end of event loop processing checks for timers that may have timed out, so you don't need to guess when the event loop has started, etc.

Binary91
7th July 2015, 11:32
Ah so a QTimer can't do anything without an event loop? That is what I think after testing a few constellations with qDebug()...
But is there any difference between the main event loop (application.exec()) and QDialogs event loop? I found out that QTimer is not interested in it, it just starts when any event loop starts...

anda_skoa
7th July 2015, 12:02
Ah so a QTimer can't do anything without an event loop?

Exactly.



But is there any difference between the main event loop (application.exec()) and QDialogs event loop?

No. The dialog's event loop is a "nested event loop", it will temporarily be in control of processing events its "parent" eventloop would otherwise process.
In this case the parent loop is the main loop.



I found out that QTimer is not interested in it, it just starts when any event loop starts...
Indeed.

Cheers,
_

Binary91
7th July 2015, 12:27
Great, thank you. So QTimer is exactly the thing for stuff that has to be called after executing an event loop.

Thank you for your support!

Cheers,