Actually I found a way to solve my problem. I use this line of code in the dialog.cpp after hide my mainwindow:
MainWindow *mainWindow = new MainWindow();
mainWindow->show();
Do you understand that this creates a different MainWindow instance from the one you used to open the dialog in the first place? Presumably in your MainWindow code somewhere you are creating the dialog on the stack, hiding the original MainWindow instance, then calling exec on the dialog. If you add the above code into the dialog class, you now have two MainWindow instances, one visible, one hidden. The new one has none of the changed state (if there was any) that occurred before the dialog was opened. It's a newly born MainWindow, with whatever defaults a new MainWindow instance has. Whatever changes the user made are tucked away in the first MainWindow instance, the hidden one.
And then after a while, the user clicks the button again. When that dialog closes, you'll now have three MainWindow instances, 2 hidden, 1 visible, all with possibly different state. Will the real MainWindow instance please stand up?
What you want to do is use signals and slots to control the visibility of the first (and only) MainWindow. Use code something like this:
void MainWindow::showDialog()
{
MyDialog dialog;
connect( &dialog, MyDialog::accepted, this, MainWindow::onDialogAccepted );
connect( &dialog, MyDialog::rejected, this, MainWIndow::onDialogRejected );
hide();
dialog.exec();
}
// A slot
void MainWindow::onDialogAccepted()
{
// You get here if the user clicks the OK, Yes, or whatever button causes the dialog to issue the accepted() signal
// So do something with it. If you need to get information from the dialog, do this:
MyDialog * pDialog = qobject_cast< MyDialog * >( sender() );
MyDialogInformation info = pDialog->getInformation();
saveInformationInApp( info );
// and finally, show the main window again:
show();
}
// And you do something similar to implement the slot MainWindow::onDialogRejected()
void MainWindow::showDialog()
{
MyDialog dialog;
connect( &dialog, MyDialog::accepted, this, MainWindow::onDialogAccepted );
connect( &dialog, MyDialog::rejected, this, MainWIndow::onDialogRejected );
hide();
dialog.exec();
}
// A slot
void MainWindow::onDialogAccepted()
{
// You get here if the user clicks the OK, Yes, or whatever button causes the dialog to issue the accepted() signal
// So do something with it. If you need to get information from the dialog, do this:
MyDialog * pDialog = qobject_cast< MyDialog * >( sender() );
MyDialogInformation info = pDialog->getInformation();
saveInformationInApp( info );
// and finally, show the main window again:
show();
}
// And you do something similar to implement the slot MainWindow::onDialogRejected()
To copy to clipboard, switch view to plain text mode
You could implement something slightly different, and connect a slot to the QDialog::finished( int ) signal, in which case you would have to look at the value of the argument passed in the signal and do something with it:
void MainWindow::showDialog()
{
MyDialog dialog;
connect( &dialog, MyDialog::finished, this, MainWindow::onDialogFinished );
hide();
dialog.exec();
}
// A slot
void MainWindow::onDialogFinished( int result )
{
// You get here if the user clicks any button on the dialog to issue the finished() signal
// So do something with it. If you need to get information from the dialog, do this:
if ( QSialog::Accepted == result )
{
// The user clicked the OK button
MyDialog * pDialog = qobject_cast< MyDialog * >( sender() );
MyDialogInformation info = pDialog->getInformation();
saveInformationInApp( info );
}
else
{
// The user clicked some other button
}
// and finally, show the main window again:
show();
}
void MainWindow::showDialog()
{
MyDialog dialog;
connect( &dialog, MyDialog::finished, this, MainWindow::onDialogFinished );
hide();
dialog.exec();
}
// A slot
void MainWindow::onDialogFinished( int result )
{
// You get here if the user clicks any button on the dialog to issue the finished() signal
// So do something with it. If you need to get information from the dialog, do this:
if ( QSialog::Accepted == result )
{
// The user clicked the OK button
MyDialog * pDialog = qobject_cast< MyDialog * >( sender() );
MyDialogInformation info = pDialog->getInformation();
saveInformationInApp( info );
}
else
{
// The user clicked some other button
}
// and finally, show the main window again:
show();
}
To copy to clipboard, switch view to plain text mode
Or you could even do this more simply without slots:
void MainWindow::showDialog()
{
MyDialog dialog;
hide();
if ( QDialog::Accepted == dialog.
exec() ) {
// Do something with the information entered in the dialog
}
show();
}
void MainWindow::showDialog()
{
MyDialog dialog;
hide();
if ( QDialog::Accepted == dialog.exec() )
{
// Do something with the information entered in the dialog
}
show();
}
To copy to clipboard, switch view to plain text mode
But you also understand, of course, that if you implement this behaviour, then your app will act like no other app on the planet except for those like it that users hate because they do unexpected things and confuse them.
What if you were in the middle of working on an important document (like writing your resume to get that great programming job), and when you clicked a button that opens a dialog, suddenly the window with all of your work in it disappeared? Oh my god, where did my resume go? I've been working on that for the last hour and it's gone! You wouldn't ever use that app again, would you, even if your document came back when you closed the dialog (or didn't, the way you originally implemented this)? You could never trust that it wouldn't lose your work - you wouldn't know if clicking that button caused a crash or not because in both cases, the main window disappears.
There is a reason why the behaviour that Wysota points out is the standard in nearly all apps (except the ones you only use once before uninstalling).
Bookmarks