Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

QMessageBox clicked standard button with open (not exec_)



  • Hi!

    Let's say I have the following QMessageBox:

    class ReallyWantToQuit(QMessageBox):
    
        def __init__(self):
            super().__init__()
            self.setModal(True)
    
            self.setText('Do you really want to quit?')
            self.setInformativeText('All data will be lost')
            self.setIcon(QMessageBox.Warning)
            self.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
            self.setDefaultButton(QMessageBox.No)
    

    Mind that I use the open method and not the classical exec_ method because the documentation for the QDialog.exec method states:

    Note: Avoid using this function; instead, use open(). Unlike exec(), open() is asynchronous, and does not spin an additional event loop. This prevents a series of dangerous bugs from happening (e.g. deleting the dialog's parent while the dialog is open via exec()). When using open() you can connect to the finished() signal of QDialog to be notified when the dialog is closed.

    How can I know when the user clicked on the "Yes" standard button? In the documentation or in the forums, all given exemples use the exec_ method or a static declaration and it is very hard to find anything using the open method. I would like the solution to be as simple as possible because this dialog will be used many times in my program and I do not want to encumber the code.

    Thanks a lot and let me know if I can do anything!



  • @Kryzar
    My opinion: save yourself the hassle! "Most people", myself included, will use QDialog::exec() for a blocking dialog/messagebox. (Which is probably why you find most examples using it rather than open()!) It's simple and it works. Just don't do the naughty things the docs tell you not to do!

    I could show you how to use then open() approach, but I really don't think it's worth the effort :)


  • Lifetime Qt Champion

    Hi,

    You can use the buttonClicked signal for exemple.



  • @JonB
    Thanks a lot for your insight, I really appreciate this kind of dialog (pin unintended). Genuine question: isn't the fact that the documentation advices you not to use exec_ a sufficient reason not to use exec_? My opinion is that in computer sciences, tools work better when they are used the way they are designed to be used for. Also, the less people use exec_, the more Qt developers are able to focus on improving open and its poor documentation. Tho I agree that if people at Qt really wanted us Qt users to use open, they should have updated the documentation.



  • @SGaist
    Thanks a lot. This solution is indeed possible. However I would like the final code to be shorter and simpler because this dialog will be used in many places in the program and not all my colleagues instantiating it will be good at Qt and there is a risk of mistakes if the need to 1. create a slot 2. understand how standard buttons work.

    So what I wish I had (and I am sorry that I was not clear enough) is a boolean yes attribute to my class ReallyWantToQuit which tells if yes or no the user really wants to quit once the dialog is closed. If we use exec_, this is really simple to do :

    class ReallyWantToQuit(QMessageBox):
        def __init__(self):
            super().__init__()
            self.setModal(True)
    
            self.setText('Do you really want to quit?')
            self.setInformativeText('All data will be lost')
            self.setIcon(QMessageBox.Warning)
            self.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
            self.setDefaultButton(QMessageBox.No)
    
            self.button(QMessageBox.Yes).clicked.connect(self.__set_yes_True)
    
        @Slot()
        def __set_yes_True(self):
            self.__yes = True
    
        @property
        def yes(self):
            return self.__yes
    

    and to use the dialog you can do

    rwtq = ReallyWantToQuit()
    rwtq.exec_()
    if rwtq.yes:
        // Do what you need to quit
    

    This does not work with open because unlike exec_, this function returns immediately. Do you know if it is possible to do this simply with open? If it is not or you feel it's not worth your time don't worry, this solution with exec_ is OK.



  • @Kryzar said in QMessageBox clicked standard button with open (not exec_):

    isn't the fact that the documentation advices you not to use exec_ a sufficient reason not to use exec_?

    Simple response: go out there and look at just how many apps/examples, both C++ & Python, use QDialog::exec(), and have done so for aeons. In just your kind of situation.

    If you want to pursue open(), that is fine and good. Just, in practice, you don't need to.



  • @JonB
    Honestly fair enough, thanks a lot.


Log in to reply