Proper way to manage the ui
-
Hi everyone!
Im think im quite an advanced programmer with Qt, but in some aspects, im completly lost, specially how to manage the user interface.
Im doing a single program and I have trouble making all of my windows close, when my main program closes.
Lets assume the program is a phone book. I want to, when I press a PushButton, (New contact), a window appear that allows you to introduce all contact information. From this window, when I press OK, i want all that data to be written on a SqlLite database, and close the window.¿How Im doing this?
I right click my project, go to add new->Qt->Qt designer form class and I add my new class. Which creates both the .cpp, .h and .ui.
Then, on my main class, I create a variable like thisNewContact *Window_NewContact;
Which is initialized like this
Window_NewContact = new (NewContact;)
On my NewContact.cpp I manage everything regarding the input of data, and saving it to the SQL database.
Then, when someone presses the button (New contact), I run this code
void MyClass::on_pushButton_NewContact_clicked(void) { if(Window_NewContact->isVisible()) { QMessageBox Error; Error.setText("You are already creating a new contact"); Error.exec(); return; } else Window_NewContact->show(); }
Well... First of all, is this approach correct? The way I do it, is I create a form class. From the form class i do all the processing, and i communicate my main program with my window via a signal/slot sistem.
Whats the problem i have?
If im using my PhoneBook, and i click on NewContact, my NewContact Window appears. If, at this moment, i close my main program, this window wont close, and the NewContact will remain even if the main program has closed.
I tried, on my main class destructor, placing adelete Window_NewContact;
but it didnt work.
Is my approach incorrect?
Or is there a way i can make sure everything closes when i close my main window.?
Another important detail is that, when this happens, if I close my "secondary Window" (new contact in this case) the Window will close but the program will keep running on the background!
The only way to close it is from Windows Task Manager. Thas quite weird, and I dont understand why.Thanks!
-
Hello and welcome @NicolasKsi
did you see this documentation? it shows the different ways to manage the ui...
Using a Designer UI File in Your ApplicationThere is the QApplication::closeAllWindows() and the QApplication::setQuitOnLastWindowClosed(bool quit) function which might be of use to you.
-
There are two basic approaches to dialog windows: modal and non-modal.
The modal one is the easiest (in pseudocode):void MainWindow::someButtonPressed() { SomeDialog dialog(someDataToPassIn, this); if (dialog.exec() == QDialog::Accepted) saveTheModifiedData(); }
This dialog window is modal i.e. it will block the main window until it is closed. It's more elegant than a "you already have that window opened" message. It's worth mentioning that it's important to pass a parent to such window (
this
in the example above) to ensure the right window icon and focus handling propagation.The other approach is non-modal i.e. the window will not block the main window while it's open:
// MainWindow.h class MainWindow { ... QPointer<SomeDialog> someDialog; } //MainWindow.cpp void MainWindow::someButtonPressed() { if (!someDialog) { someDialog = new SomeDialog(someDataToPassIn, this); someDialog->setAttribute(Qt::WA_DeleteOnClose); //this line is optional } someDialog->show(); }
Again, it's important to pass the parent to the dialog. Apart from the previous benefits it will in this case also assure that the dialog is destroyed when the main window is closed. The setting of the attribute is optional - if you set it the dialog will be destroyed automatically when it is closed. If you don't, closing the window will not destroy it (it will open faster next time). It will be destroyed along with main window.
-
Hi, thanks for the information.
Ive understood what you told me, not sure how to do it though. To be more specific, how to create the dialog of type "SomeDialog".
Ive tried first of all doing the simpleQDialog TestDialog; TestDialog.exec();
and an empty Dialog appears. Now the question is how do I edit this dialog, and how do I manage the comunication of information between the Dialog and main program. (Guess the signal/slot system I was using wasnt the correct approach)
If I go to
Right click on project->Add new->Qt->Qt designer form
I can create the visual appearence for my new Window. Now, how do i make my TestDialog look like that?
Was looking a "SetUpUi" from QDialog, but it doesnt exist.
I know that probably the form appearence can be modified by writing code, but I was hoping if it was possible to do with QtCreater ui instead.
Thanks in advance -
There are couple of ways to do all this but lets stick to the basics.
Right click on the project -> Add new -> Qt -> Qt Designer Form Class.
This will create a .ui designer file and a .h/.cpp files for a class that uses that ui. If you already have a class and you just want to attach the .ui generated code you can do the above and see how an integration is done.
Ok, lets say you now have a dialog class with a designer ui. Lets call it SomeDialog. As I mentioned earlier it's important to pass a parent to a dialog, so that it has proper focus and window ordering, so the basic setup would be:void MainWindow::someButtonPressed() { SomeDialog dialog(this); dialog.exec(); }
Now to the data passing. There are again couple of ways to do that. One of the easier ones is via a data structure. For a simple example lets say you have a structure that definess some login information:
struct LoginData { QString login; QString password; };
You keep that in your MainWindow:
class MainWindow { private: LoginData loginData; }
and you'd like to fill it in via dialog. You can do that like this for example:
void MainWindow::someButtonPressed() { SomeDialog dialog(loginData, this); if (dialog.exec() == QDialog::Accepted) loginData = dialog.data(); }
For that to work you'd have a constructor of your dialog looking something like that:
SomeDialog::SomeDialog(const LoginData& loginData, QWidget* parent) : QDialog(parent) { ui->loginLineEdit->setText(loginData.login); ui->passwordLineEdit->setText(loginData.password); }
and a getter function to retrieve the user input:
LoginData SomeDialog::data() const { LoginData loginData { ui->loginLineEdit->text(), ui->passwordLineEdit->text() }; return loginData; }
You can also go with signals/slots. There's no "one true way"™.