QT Creator C++ : Passing information from QDialog to MainWindow - c++

I'm trying to make a program with the following:
In MainWindow (QMainWindow), I have a button AddUser that's opens a secondary window (QDialog) where I have 3 spaces to write the name, email and mobile number of user to add to program.
I want that, after introduce all those information, I click in Add button and the window closes and the information I wrote goes to a vector of User (vector<User> users) located in MainWindow so I can use it.
I have all of this stuff done, just the passing information I can't do.
I already searched about it but I just found make a login window (secondary window opens before main window and after introduce data it closes the login window and open the main window with that information saved). I want basically that but the difference is that secondary window opens when I click in a button in MainWindow
But it's not working well, can someone help me?
I have this code (based on Login context code):
adduserwindow.h (secondary window)
signals:
void add(const User & user);
adduserwindow.cpp
void AddUserWindow::on_button_addUser_clicked() // Add button after write the info
{
QString name = ui->text_name->text();
QString email = ui->text_email->text();
QString mobile = ui->text_mobile->text();
User u1(name.toStdString(),email.toStdString(),mobile.toStdString());
users_.push_back(u1);
emit add(u1);
}
mainwindow.h
public:
void setUser(const User &user);
private:
User mUser;
mainwindow.cpp
void MainWindow::on_button_adduser_clicked() // AddUser button in MainWindow
{
AddUserWindow adduser_window(this);
adduser_window.exec();
QObject::connect(&adduser_window, &AddUserWindow::add, [this](const User user) {
this->setUser(user);
this->show();
});
}
void MainWindow::setUser(const User& user)
{
mUser = user;
qDebug()<<mUser.toString(); //toString() is a method of User class to convert std::string to QString
}
Obs: I have this at the end of User.h:
Q_DECLARE_METATYPE(User)

Just to leave an answer for future visitors... The issue here was that QDialog's exec() function does not return until the user closes the dialog. In this case the simple solution is to make any signal connections before calling exec().
However, its documentation recommends using open(), or alternatively show() for modeless dialogs. These functions both return immediately, so the dialog's lifetime would need to be tied to its parent window, by giving it dynamic storage duration:
void MainWindow::on_button_adduser_clicked() // AddUser button in MainWindow
{
auto* adduser_window = new AddUserWindow(this);
QObject::connect(adduser_window, &AddUserWindow::add, [this](const User user) {
this->setUser(user);
this->show();
});
adduser_window.open();
}
That is the idiomatic Qt way of doing it and I would recommend it, because it works whether or not the dialog (or other QObject) will actually outlive the function.

Related

How do I open a window depending on the user's choice in the previous window? in Qt

Okay so basically I am creating an interface that has a seller and a customer, and so the user chooses which option he wants and is taken to the the "registration window". After filling the questions he presses continue and it takes him to either the "seller" interface or "customer" interface.
I want to know how on Qt do I make the
void RegistrationWindow::on_continue_pushButton_clicked()
take the user to the interface of the chosen option in the previous window.
I know I will need to use an If statement, but I don't know what will the condition be or how i will make it work.
Here is the code for the registration window continue button:
void RegistrationWindow::on_continue_pushButton_clicked()
{
hide();
if ()
customer = new CustomerWindow(this);
customer->show();
if()
seller = new SellerWindow(this);
seller->show();
}
And here is the code for the main window buttons:
void MainWindow::on_customer_pushButton_clicked()
{
hide();
registration = new RegistrationWindow(this);
registration->show();
}
void MainWindow::on_seller_pushButton_clicked()
{
hide();
registration = new RegistrationWindow(this);
registration->show();
}
If any information else is needed I will provide it.
Thank you!
I have not tried anything yet because I dont understand

Qt - How to handle memory management for dialogs?

I am running into the following issue:
Users presses "Ctrl+N" which goes into function MainWindow::newAction()
In MainWindow::newAction(), create a QDialog dlg(centralWidget()) and call dlg.exec()
While dlg is open, users pressed "Ctrl+N" again
The result is that dlg never gets deleted (it will only get deleted once centralWidget() gets deleted).
The call stack is something like this:
MainWindow::newAction ()
...
MainWindow::newAction()
I am wondering how to handle this case. I want all of the local dialog variables from the first call to newAction() to be deleted by the time we go into the function newAction() again.
You also can try something like this:
void MainWindow::newAction() {
const auto dialog = new MyDialog(centralWidget());
// When user will close the dialog it will clear itself from memory
connect(dialog, &QDialog::finished, [dialog]() {
dialog->deleteLater();
});
dialog->exec();
}
However, a good move would be to stop user from summoning more QDialogs than a single one, given that this one is a modal dialog(might be a good idea to keep this dialog pointer as a class member and check is it on screen already before calling exec() on it.
If i understood the question right, you want one dialog to be opened and want to delete it before a new dialog request comes in?
If that's the case you can do following:
In MainWindow.h declare QDialog *dlg = nullptr
In your MainWindow.cpp newAction() function you can do following:
void newAction()
{
if(dlg != nullptr)
{
dlg->close();
dlg->deleteLater();
//or
//dlg->destroy(); // this will immediately free memory
}
dlg = new QDialog(centralWidget());
...
//dlg->exec(); // This will automatically make QDialog modal.
dlg->show(); // This will not make a QDialog modal.
}
I hope this will help. Remember QDialogs when displayed with exec() they automatically behave as Modal window. show() will make it non-modal.

How to close parent UI window when child UI window is open in QT

I have multiple UI windows in my QT project. When a new UI window opens, the previous UI window must be closed, that is, at every point of time only one UI window must be open. How can this be done?
I did that before and i suggest you to not close(delete) UI.
just hide it and when you need it show it again.
check this code:
when user click to see second UI:
void MainApp::on_btnSettings_clicked()
{
this->hide();
settingsManager = new SettingsManager(); // put this line in constructor
settingsManager->show();
}
on second UI on closing form(or back button) emit a signal:
void SettingsManager::closeEvent(QCloseEvent *event)
{
emit settingsBackToMainApp();
}
on main hide second class and show main:
void MainApp::settingsBackToMainApp()
{
settingsManager->hide();
this->show();
}
connect signal to slot:
connect(settingsManager,&SettingsManager::settingsBackToMainApp,this,&MainApp::settingsBackToMainApp); // put this line in constructor

Qt: button - going back from "help.cpp" to "mainwindow.cpp"

I'm new at Qt. I've created small application and I created second page help.cpp. On MainWindow.cpp I have a button, that switches to help.cpp page.
Function which switches to "help" page:
void MainWindow::on_box1button_clicked()
{
helpwindow = new help(this);
helpwindow->show();
}
This code works properly.
On the "help" page I've got a QButton, which will switch back to mainwindow.cpp. How Can I code that button to actually make this action?
If your intention by "switching" is hiding one window and showing another one, so you can simply pass a reference of the main window to your help window and there when you want to switch back, you can hide/close itself and show the main window.
MainWindow (this code is fine)
helpwindow = new help(this);
helpwindow->show();
HelpWindow
When you want to switch back to the main window, you can do this:
// Hide the HelpWindow itself
// or this->close()
this->hide()
// Show the MainWindow (i.e. the parent window)
QWidget *parent = this->parentWidget();
parent->show();
Since you are creating a new help(this); on mainwindow it is better to close the help window
Use
this->close();

How to properly clean-up a QWidget / manage a set of windows?

Let's say I have 2 windows in my application, and two classes responsible for them:
class MainWindow: public QMainWindow and class SomeDialog: public QWidget.
In my Main Window I have a button. When it is clicked, I need to display the second window. I do it this way:
SomeDialog * dlg = new SomeDialog();
dlg.show();
Now, the user does something in the window, and closes it. At this point I want to get some data from that window, and then, I suppose, I will have to delete dlg. But how do I catch the event of that window being closed?
Or is there another way not to have a memory leak? Maybe It would be better to create an instance of each window on startup, and then just Show()/Hide() them?
How do I manage such a case?
It is advised to use show() / exec() and hide() instead of dynamically creating the dialog every time you want to show it. Also use QDialog instead of QWidget.
In the constructor of your main window create it and hide it
MainWindow::MainWindow()
{
// myDialog is class member. No need to delete it in the destructor
// since Qt will handle its deletion when its parent (MainWindow)
// gets destroyed.
myDialog = new SomeDialog(this);
myDialog->hide();
// connect the accepted signal with a slot that will update values in main window
// when the user presses the Ok button of the dialog
connect (myDialog, SIGNAL(accepted()), this, SLOT(myDialogAccepted()));
// remaining constructor code
}
In the slot connected to the buttons's clicked() event simply show it, and if necessary pass some data to the dialog
void myClickedSlot()
{
myDialog->setData(data);
myDialog->show();
}
void myDialogAccepted()
{
// Get values from the dialog when it closes
}
Subclass from QWidget and reimplement
virtual void QWidget::closeEvent ( QCloseEvent * event )
http://doc.qt.io/qt-4.8/qwidget.html#closeEvent
Also it looks like the widget you want to show is a dialog. So consider using QDialog or it's subclasses. QDialog has useful signals you can connect to:
void accepted ()
void finished ( int result )
void rejected ()
I think you are looking for the Qt::WA_DeleteOnClose window flag: http://doc.qt.io/archives/qt-4.7/qt.html#WidgetAttribute-enum
QDialog *dialog = new QDialog(parent);
dialog->setAttribute(Qt::WA_DeleteOnClose)
// set content, do whatever...
dialog->open();
// safely forget about it, it will be destroyed either when parent is gone or when the user closes it.