0

I have QDialog designed by PyQt5 designer, I basically need to execute this dialog box from QMainWindow app in a separate process. Although I don't get any errors with below code but the Dialog box never show up. Can anyone tell me what am I doing wrong?

Main Window App on button click:

def alertWindow(self, alertInfo):
    p = Process(name="alertwindow", target=alertWindowCustom, args=(alertInfo,))

Dialog Box Class:

class alertWindowCustom(QDialog, Ui_alertwindow):
    def __init__(self, alertwindowData):
        QDialog.__init__(self)
        self.setupUi(self)
        self.alertwindowData = alertwindowData


        self.run()
        self.exec_()

    def run(self):
        print("brah", self.alertwindowData)

If I just call alertWindowCustom class as a = alertWindowCustom(alertInfo) without a process, the dialog box is created but the MainWindow become unresponsive.

If using QThread is a better option to use over multiprocessing, I would rather use that.

pefile
  • 69
  • 6
  • Widgets cannot be created outside the main thread, let alone external processes. Why do you want to do that? – musicamante May 02 '22 at 20:41
  • @musicamante so, what is the proper way to pop up a dialog box without blocking the mainwindow? – pefile May 02 '22 at 20:52
  • @pefile Keep a reference to the dialog (and/or give it a parent) and open it with `show()`. – ekhumoro May 02 '22 at 21:14
  • @ekhumoro but that doesn't resolve the issue of MainWindow becoming unresponsive – pefile May 02 '22 at 21:25
  • @pefile remove `self.exec_()` from the `__init__`, just call `show()`. As the [documentation explains](https://doc.qt.io/qt-5/qdialog.html#exec): "`exec()` Shows the dialog as a modal dialog, blocking until the user closes it." – musicamante May 02 '22 at 23:24
  • @musicamante I replaced `self.exec_()` with `self.show()`, the window pops and instantly closes. – pefile May 03 '22 at 00:12
  • @pefile as already explained by ekhumoro, you need to keep a reference to the dialog (`self.dialog = alertWindowCustom()`) or set a parent (`dialog = alertWindowCustom(self)`, which obviously must be implemented in the `__init__` arguments and in the super class init. Please read more carefully what's being suggested in comments, and do some research as there are dozens, if not hundreds of posts about that issue. – musicamante May 03 '22 at 00:22

1 Answers1

0

Credit to @musicamante and @ekhumoro.

You don't have to use a thread or a process to create a dialog box that does not block main thread.

To keep your MainWindow responsive while dialog box is open, avoid using exec_() but rather use show(). This will create a non-modeled dialog box and store the dialog box in memory which you will always have to keep a reference of. To do that make a reference of it in your MainWindow as below:

self.alertwindowclass = alertWindowCustom(alertInfo)

Make sure to use self, otherwise as soon as the function is done, dialog box data will be moved to python recycle bin which will destroy you dialog box.

My new full code is below:

class mainWindow(QMainWindow):
    # Below function is called to create the dialog box
    def alertWindow(self, alertInfo):
        self.alertwindowclass = alertWindowCustom(alertInfo)


class alertWindowCustom(QDialog, Ui_alertwindow):
    def __init__(self, alertwindowData):
        QDialog.__init__(self)
        self.setupUi(self)
        self.alertwindowData = alertwindowData
        self.run()

        self.show()

    def run(self):
        print("brah", self.alertwindowData)

I had to read many forms to gather this information. I wrote an article here if you want to learn more about it. Hope that help people in the future.

pefile
  • 69
  • 6
  • You do not need to "read many forms" - it's all explained in the [docs for QDialog](https://doc.qt.io/qt-5/qdialog.html#details). There are also dozens of questions on SO which deal with the same topic. The last thing we need is yet more duplicated questions and articles. – ekhumoro May 03 '22 at 10:18