Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 to emit() 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 the public: section of DialogInput something like QString getSite() const {return ui.lineEdit->text();}.
    Then you just call

    DialogInput 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). After QDialog.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 he deletes the dialog himself), it may be because I use Python/PyQt.


  • Lifetime Qt Champion

    Hi,

    An additional note, you are leaking dialogs object with your implementation.

    You create a new dialog each time your function is called.


  • Qt Champions 2019

    @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 slots

    I 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 cannot delete a dialog. Python does that for us --- or not --- behind the scenes. I cannot recall all the ins and outs, but I found that setting Qt::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.


  • Qt Champions 2019

    @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)



  • @jsulm , @VRonin

    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 (via self.something). That is effectively an anonymous function (called a "closure", I think) which references self 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 via Qt::WA_DeleteOnClose. Hence my decision on advisable default behaviour for me/Python.....


Log in to reply