Get user input from QDialog
-
Hi,
How can I grab "send" data input from user from QDialog using signal/slots?Right now I've got something like this:
connect(ui.okButton, &QPushButton::clicked, this, &DialogInput::buttonClicked);
void DialogInput::buttonClicked() { setSite(); }
void DialogInput::setSite() { const QString siteQString = ui.lineEdit->text(); site_text = siteQString.toLocal8Bit().constData(); }
Right after okButton is been clicked values are saved in private fields of "DialogInput" class. How can I "send" those values to functions in other classes? In DialogInput other objects and they're methods are inaccessible.
Dialog is invoking this way:
dialog = new DialogInput(); dialog->exec();
-
@Essentialfloss7-111XfacF
The usual way is toemit()
a signal from the dialog which outside world can connect slots to. That's the Qt way of doing things, and does not require your dialog to know who the listeners are, nor to expose methods for outside world to call. -
It happens rarely but I disagree with @JonB
The usual way (for dialogs, for other widgets Jon's suggestion is 100% correct) is just to have a getter for the property you want. Add in thepublic:
section ofDialogInput
something likeQString getSite() const {return ui.lineEdit->text();}
.
Then you just callDialogInput dialog; if(dialog.exec()){ qDebug() << dialog.getSite(); }
-
I've got "working" solution that look like @VRonin solution. But I think there's something wrong with that. I think in my solution data are passed and saved to db after closing Dialog (I want to save into db after clicked -okButton in DialogInput window :
In MainWindow constructor I've got initialization of database class (db) and connect to pushButton which is invoking DialogInput window
db = new Database(); connect(ui.insertBtn, &QPushButton::clicked, this, &MainWindow::runUserInputDialog);
void MainWindow::runUserInputDialog() { dialog = new DialogInput(); dialog->exec(); getters(); setters(); db->insertValues(); }
void MainWindow::getters() { site_text = dialog->getSite(); login_text = dialog->getLogin(); pass_text = dialog->getPass(); } void MainWindow::setters() { db->setSite(site_text); db->setLogin(login_text); db->setPasswd(pass_text); }
-
@VRonin , @Essentialfloss7-111XfacF
It happens rarely but I disagree with @JonB
:) I read the OP's question as
How can I grab "send" data input from user from QDialog using signal/slots?
How can I "send" those values to functions in other classes?I thought he actively wanted to "post" data out from his dialog.
Re-reading, maybe OP is only asking to access data in fields on the dialog, I don't know?
One thing about the approach you two are using now, just to be aware of. I have all my dialogs default to
Qt::WA_DeleteOnClose
(https://doc-snapshots.qt.io/qt5-5.9/qt.html#WidgetAttribute-enum). AfterQDialog.exec()
the dialog has closed & gone, you cannot access its members, so this approach won't work. This may not affect the OP (so long as hedelete
s the dialog himself), it may be because I use Python/PyQt. -
Hi,
An additional note, you are leaking dialogs object with your implementation.
You create a new dialog each time your function is called.
-
@Essentialfloss7-111XfacF said in Get user input from QDialog:
data are passed and saved to db after closing Dialog (I want to save into db after clicked -okButton
Isn't the dialog closed when you click on Ok button? So, what is would be the difference?
If your dialog is not closed when Ok button is clicked, then you will need to go for the solution suggested by @JonB -
The normal approach with ok/cancel buttons is to connect them to the
QDialog::accept
/QDialog::reject
slotsI have all my dialogs default to Qt::WA_DeleteOnClose
If you want to go down this rabbit hole: https://blogs.kde.org/2009/03/26/how-crash-almost-every-qtkde-application-and-how-fix-it-0
-
@VRonin
I'm not sure what your KDE link is saying about my situation. My problem (not the OP's/yours/C++) is Python/PyQt. We cannotdelete
a dialog. Python does that for us --- or not --- behind the scenes. I cannot recall all the ins and outs, but I found that settingQt::WA_DeleteOnClose
was the best way to ensure the dialog actually gets deleted.95% of my dialogs do not have extra buttons/fields/callbacks, and do not need to be accessed after the user closes. For the few that do require post-close access, my code explicitly removes that flag and handles clear up itself. It's just my default. I just wanted to make OP aware of potential pitfall when trying to access widgets on dialog after it has been
exec()
ed. -
@JonB said in Get user input from QDialog:
We cannot delete a dialog
Isn't that happening automatically as soon as the dialog instance goes out of scope?
-
@jsulm said in Get user input from QDialog:
@JonB said in Get user input from QDialog:
We cannot delete a dialog
Isn't that happening automatically as soon as the dialog instance goes out of scope?
In Python I don't think that's the case if you pass a parent to the dialog (I'm not sure though)
-
Isn't that happening automatically as soon as the dialog instance goes out of scope?
Ohhh, noooo ! Welcome to my Python hell :( Don't be fooled by claims that Python "just works". :) I don't know whether you/others are Pythonistas, this should be relevant not just to PyQt but also to new Qt for Python/PySide2, but briefly....
Python automatically reference counts objects. Object is not freed if there are any existing references to it, till reference count reaches 0. Even trying to go Python
del
, which you might think would behave as C++delete
, does not delete --- it only decrements reference count by 1."Normally" this works well. However, there are cases where you have reference counts you don't even know about, which prevent disposal! :( I did say I did not recall all the ins & outs, but the most obvious & horrible one is if you have lambdas in the dialog code which reference
self
(this
) in its parameters. I'm not a great fan of lambdas, but there are a lot in the code I have inherited. Many are innocuous-looking:self.widget.signal.connect(lambda: method(self.something))
This creates a lambda which references
self
(viaself.something
). That is effectively an anonymous function (called a "closure", I think) which referencesself
and so increments the dialog's reference count. Python is not clever enough to understand that it is local to the dialog and so does not need to increment to prevent disposal. As a consequence, Python is never going to dispose this dialog, because its count will never reach 0! :( [This issue does not apply only to e.g. Qt, it's a general Python issue with lambdas.]I tested by walking
QtWidgets.QApplication.allWidgets()
and sure enough such dialogs (together with all their widgets) never get freed via out-of-scope once opened, till application closure. They do get freed if you explicitly close the dialog viaQt::WA_DeleteOnClose
. Hence my decision on advisable default behaviour for me/Python.....