Why does the window not pop up? - c++

I have the following source code:
Processmethod()
{
QDialog *ProcessMessage = new QDialog;
Ui::DialogProcessMessage Dialog;
Dialog.setupUi(ProcessMessage);
ProcessMessage->setModal(true);
ProcessMessage->setAttribute(Qt::WA_DeleteOnClose);
ProcessMessage->show();
PROCESSES START
}
After I want to show the QDialog "ProcessMessage" there are three QProcess processes included in three different following methods. If I disable these methods with // the popup window appears just fine, but if I enable the methods, the processes run fine, but the popup window does not appear. Any ideas/solutions ? greetings

Your window do not show until Process method is not return because main application loop implemented in main function
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog w; // or other window
w.show();
return a.exec(); // main app loop (all drawing procedures called from here
}
So if you call your PROCESSES START nothing happened until Process method returns in QApplication::exec()
You can start your processes in separate thread and send progress notification to you dialog by implementing signals\slots in queued mode

The dialog cannot be shown until your code execution exits ProcessMethod(). If you are using the QProcesses synchronously (by calling any of the waitForXXX methods), then this would cause the problem you are seeing. Anything else that holds up the main thread would also cause this problem.

Related

Proper way to initialize and terminate a Qt Application?

I am currently coding a program in C++/ Qt 5.9 to control a 3D Printer.
I have divided the project into several libraries :
The GUI Lib: The view
The Device Lib: Control each device (movement, printing tool, sensors)
The Controller Lib: Links the View with the Device lib
etc...
My problem is that I do not know how to initialize and terminate properly the execution of the program. More specifically, the Device library has a class named DeviceManager with two functions :
initialize() : which connect to each device and initialize them. This actions can take several seconds (10s for example)
finalize() : which closes all the connexions, can also take several seconds
What I would like to do is initialize the Device Lib in the right place without blocking the GUI and then finalize it in the right and not block the GUI
This is my main code :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
My solution now is to call DeviceManager::initialize() in the MainWindow constructor and DeviceManager::finalize() in the MainWindow::closeEvent().
The problem: even if I use concurrency to initialize and finalize in a different thread, the application displays its window several seconds after it was launched and the display freezes when the application is closed because it has to wait for the finalize function to be done.
How should I properly handle this initialization and finalization problem, please ? Do I need to reimplement the QApplication class? Do I try and do it in the main? Do you know any great example of an open source application doing that kind of initialize and finalize work?
The problem: even if I use concurrency to initialize and finalize in a different thread, the application displays its window several seconds after it was launched and the display freezes when the application is closed because it has to wait for the finalize function to be done.
You could start the initialize() function as own detached thread before starting the MainWindow. This could cause problems if the initializing thread doesn't terminate before the first initialized "thing" is needed. Something like:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
std::thread{initialize}.detach();
MainWindow w;
w.show();
finialize();
return a.exec();
}
To prevent the problem, and maybe lock some function in the GUI, then you probably need to have a state variable that it sets under a mutex on its way out, and which you examine under a mutex to see if it has been set.

Totally deleting the QApplication Instance and recreating it in another thread

How can I totally remove the QApplication instance, so it can be possible to recreate it again in a sheared library.
If I have such a following code:
int main(int argc, char ** argv) {
QApplication *app = new QApplication(argc, argv);
MyWindow dialog;
dialog.show();
app->exec();
return 0
}
I want to be able to delete the instance after quiting the app (closing the application after app.exec())
I have tried to do the following:
app->setQuitOnLastWindowClosed(false);
app->quit();
delete app;
But non of them could be worked. I want to remove the QApplication instance like I did not create before.
The QApplication in my shared library always works if I did not define the QApplication in the main.
The library (lib) and the main application (app) are using different copy of Qt.
I am developing the app, the lib is imported to my app.
After closing the first dialog, I am using an event to trigger the thread in the library which it is waiting for this event.
You don't need to do that, because QApplication can only ever be created in the main thread. If the library and the main executable share the same Qt library, presumably the main application already created the QApplication object and will run the event loop for you. So the only thing you need to do in the library is to create some objects and the event loop will process their events.
If the main executable doesn't use Qt, then you should create the application in the main thread, prime its event loop, and let the native event loop dispatch events for you.
Alas, to directly answer your question: presumably you want to do some stuff after app.exec() returns. Your code could simply be, then:
int main(int argc, char ** argv) {
{
QApplication app{argc, argv};
MyWindow dialog;
dialog.show();
app.exec();
}
doSomething();
}
If I close the first dialog, the event loop will be left. Is it possible to keep the event loop?
Yes. You could clear the Qt::WA_QuitOnClose attribute of the first dialog. Or, preferably, set it on your dialog - the application won't quit as long as there are any dialogs with QT::WA_QuitOnClose still open.
Thus, for the second dialog, call:
secondDialog->setAttribute(Qt::WA_QuitOnClose);
Alternatively, if you don't have a pointer to the dialog, you can iterate all top-level widgets and clear (or set) the attribute on all of them:
for (auto widget : qApp->topLevelWidgets())
widget->setAttribute(Qt::QA_QuitOnClose, false);

How to show dialog when main window became visible for the very first time in Qt widgets application?

I have Qt widgets application that has to authorize user with web service request before he can use the program. If user can not sign in for any reason, I have to exit the application.
.NET Framework implements Load event for that: when user sees window for the very firt time (the keyword here is "user sees"), it is possible to display dialog; if dialog result is not OK, we call close on main application window.
With Qt, we can override showEvent. However, it fires before user really can see main window. When I create dialog in showEvent, it appears without main window, and when I close main window in showEvent, it doesn't close (because it is not opened at the moment) and appears later event if user failed to sign in. It appears even after QApplication::quit() call.
My question is: is there a way to receive exactly the same functionality as in .NET Framework/Windows API and get event fired when user really sees window and not when he "may be sees something or will see soon"? It is possible to start timer from showEvent to get similar effect, but I think it is not professional, because you never know what may happend in user computer (may be its CPU works on 100% now), and you can not have real guarantee that timer will show dialog at correct moment.
I would try to create MainWindow and hide() it be default. The only widget to be shown at startup should be then the Login-Dialog. I would connect the successful login with the show() slot of the QMainWindow and the login failure - with the quit slot of the application.
I usually do something like this in my main.cpp:
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
LoginDialog dialog;
if(!dialog.exec()){
return 1;
}
MainWindow w;
w.show();
return a.exec();
}
that (of course) after having LoginDialog defined to inherit from QDialog and MainWindow defined to inherit from QMainWindow.
Create the main dialog at application startup, and only create the main window when the service responds positively.
You don't really need to dig deep in the event handlers.

How to close correctly a Qt program?

When I try to close my Qt program, it just keeps running in the background though there's no window anymore.
Basically, I would like to know what I should do so it closes properly when I click the red cross on my main window (which has no parent).
Following this link, I tried a few things like :
QApplication app(argc, argv);
//...
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
return app.exec();
or
QApplication app(argc, argv);
//...
app.setQuitOnLastWindowClosed(true);
return app.exec();
but neither work, the process still stays in memory, after the cross is clicked.
Then, how can I close correctly my program ?
You can close your application manually using QApplication::quit().
By default the execution is terminated when the last top level window with the Qt::WA_QuitOnClose attribute has been closed. You don't need to connect lastWindowClosed to quit because it repeats the default setQuitOnLastWindowClosed behavior. You don't need to do setQuitOnLastWindowClosed(true) either because it's true by default. The code you've posted does nothing (if nothing is changed somewhere else).
Possible solutions:
Check your main window attributes. Maybe you have removed Qt::WA_QuitOnClose attribute.
If you have reimplemented closeEvent in your top level window, check that close event is being accepted.
Check if there are some other top level widgets that may be hidden but not closed. Use QApplication::topLevelWidgets() to list them.

Qt Application hangs on exit (after QDialog exec)

I'm using Qt to build a UI and I need to have a dialog window show up before the main app window, so that the user can select some files to load ans things like that.
What I've got is a fairly simple main:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
IView *view = new QtView();
view->showView();
int rc = a.exec();
std::cout << "exit" << std::endl;
return rc;
}
the QtView class is the concrete implementation of the IView interface.
It has the mainwindow instance and a QDialog instance too. int the view->showView() method this is what I've got:
void QtView::showView()
{
this->_configDialog->exec();
this->_mainAppWindow->show();
}
It works fine, the dialog opens and when the user clicks OK, exec returns and the main window appears. The problem is that when I quit the main window I get a zombie process and the app just seems to hang even though all the windows have been closes and I never get the "exit" I print out in the main just before the main returns.
I'm not sure what I'm doing wrong, but I get the same resutl even if I click on the cross to close the dialog, the main window opens up, and once closed the whole things just hangs there.
If anyone has any advice, that would be cool.
Thanks.
I Fixed my problem.
I used the accepted/rejected/finished(int) signal from the QDialog to trigger the show slot on the main app window, and display it if the dialog was accepted.
Thanks for the help anyway.
I think the possible reason for this behavior is that your configuration dialog may not have a parent widget set on it (it's a blind guess though as you haven't cited the relevant portion of the code). That's because QApplication by default would only quit when all the windows with no parent are closed. And the thing is, a dialog is not a window, technically - it has the Qt::Dialog window type rather than Qt::Window. That means any "orphaned" dialog, that is closed, will still prevent the application from exiting automatically.
The solution?
Either giving a parent to the dialog or enabling the Qt::WA_QuitOnClose attribute:
this->_configDialog->setAttribute(Qt::WA_QuitOnClose);