Python: PyQt Popup Window
Question: So I've been creating my GUI with Qt for my Python application. I've now come
to a situation where after a button has been pushed the appropriate deferred
gets executed, we perform some tasks then I need to open up a separate window
that contains one or two things. But I can't seem to figure out how to create
this new separate window. Could anyone give me an example of how to create
one?


Answer: A common error that can drive you crazy is forgetting to store the handle of
the popup window you create in some python variable that will remain alive
(e.g. in a data member of the main window).

The following is a simple program that creates a main window with a button
where pressing the button opens a popup

    
    
    #!/usr/bin/env python
    #-*- coding: utf-8 -*-
    
    import sys
    from PyQt4.Qt import *
    
    class MyPopup(QWidget):
        def __init__(self):
            QWidget.__init__(self)
    
        def paintEvent(self, e):
            dc = QPainter(self)
            dc.drawLine(0, 0, 100, 100)
            dc.drawLine(100, 0, 0, 100)
    
    class MainWindow(QMainWindow):
        def __init__(self, *args):
            QMainWindow.__init__(self, *args)
            self.cw = QWidget(self)
            self.setCentralWidget(self.cw)
            self.btn1 = QPushButton("Click me", self.cw)
            self.btn1.setGeometry(QRect(0, 0, 100, 30))
            self.connect(self.btn1, SIGNAL("clicked()"), self.doit)
            self.w = None
    
        def doit(self):
            print "Opening a new popup window..."
            self.w = MyPopup()
            self.w.setGeometry(QRect(100, 100, 400, 200))
            self.w.show()
    
    class App(QApplication):
        def __init__(self, *args):
            QApplication.__init__(self, *args)
            self.main = MainWindow()
            self.connect(self, SIGNAL("lastWindowClosed()"), self.byebye )
            self.main.show()
    
        def byebye( self ):
            self.exit(0)
    
    def main(args):
        global app
        app = App(args)
        app.exec_()
    
    if __name__ == "__main__":
        main(sys.argv)
    

What I think can be surprising for Python users and may be is the problem you
are facing is the fact that if you don't store a reference to the new widget
in the main e.g. by using `w = MyPopup(...)` instead of `self.w =
MyPopup(...)` the window apparently doesn't appear (actually it's created and
it's immediately destroyed).

The reason is that when the local variable `w` goes out of scope as no one is
explicitly referencing the widget the widget gets deleted. This can be seen
clearly because if you press again the button you'll see that as the second
popup appears the first one is closed.

This also means that if you need to create several popups you have for example
to put them in a python list and you should remove them from this list once
the popups are closed by the user. The equivalent in the example could be
changing to `self.w = []` in constructor and then doing
`self.w.append(MyPopup(...))`. Doing that would allow you to open several
popups.

