Jack
Jack

Reputation: 355

How to call multiple Dialogs in PyQt?

I have a main dialog and on that dialog there is a button. When the button is clicked, I want to open an another dialog.

Main Dialog code (Function which is called when the button is clicked in the main dialog):

def add_host(self):
        x=add_host.Ui_Dialog1()
        x.main()

default function:

if __name__ == "__main__":
    import sys
    global app
    app = QtGui.QApplication(sys.argv)
    Dialog = QtGui.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())

Secondary dialog (add_host.py) code snapshot:

def main(self):
        app1 = QtGui.QApplication(sys.argv)
        Dialog1 = QtGui.QDialog()
        ui1 = Ui_Dialog1()
        ui1.setupUi1(Dialog1)
        Dialog1.show()
        sys.exit(app.exec_())

So when I run the code, it opens the secondary dialog but when I close it, it just freezes, and I get this error message:

 File "testbot.py", line 175, in add_host
    x.main()
  File "/home/ppp/ppp/add_host.py", line 74, in main
    sys.exit(app.exec_())
NameError: global name 'app' is not defined

Which does make sense, but I have no idea how to resolve it. I try several combinations without success, including adding and deleting app.exec_().

Upvotes: 1

Views: 5199

Answers (2)

jdi
jdi

Reputation: 92657

You cannot create multiple QApplications inside of the same script and thread. You are only supposed to have one...

This should be more like:

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Dialog = QtGui.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())

No global app. Although you should be doing your setupUI from within the class of your dialog.

Then when you want to show another dialog from with your app...say main(), you just create it and call show()

Here is a really basic example:

class Dialog(QDialog)
    def __init__(self, parent):
        super(Dialog, self).__init__(parent)
        self.otherDialog = QDialog(parent=self)

        self.otherDialog.show()


if __name__ == "__main__":
    app = QApplication([])
    dialog = Dialog()
    dialog.show()
    app.exec_()

You create a single QApplication and start its event loop by calling exec_(). From that point on, your main application is free to create more QWidgets. You never create another QApplication again at this point.

Also, I dont understand this part of your code:

def add_host(self):
    x=add_host.Ui_Dialog1()
    x.main()

The fact that you are calling a main() method on your UI object makes me think you are modifying the UI file and adding functionality to it, which you should not be doing. That ui file is subject to be overwritten every time you make changes in QT Designer and save out a new one. You should only be importing it and using its setupUI() method to apply it to your own custom classes.

A note about organization of your modules

When you are designing a PyQT application, you will always have a single entry point that will be called to start your app. This is the single and only location that should be creating your QApp and starting the event loop, and is usually done with in a if __name__ == "__main__" block to ensure its only done when its the main script. It should not be done within methods of your objects. For all your other modules where you define other Dialog, Widgets, etc, these should simply be classes that you import. As long as you have a running QApp, you are free to create and show these widgets.

Upvotes: 5

hooblei
hooblei

Reputation: 3240

Your code sample is a bit confusing - I don't understand why you have two mains, etc - anyway, maybe it's just a typo in add_host.py (app1.exec_() instead of app.exec_())

def main(self):
    app1 = QtGui.QApplication(sys.argv)
    ...
    sys.exit(app1.exec_())

Upvotes: 0

Related Questions