I'm learning to use the pyqt libraries and this code won't work (no output):

#!/usr/bin/env python2
# -*- coding: utf-8 -*-

from pomocni import Ui_MainWindow
from PyQt4.QtGui import QMainWindow, QApplication
from PyQt4 import QtCore
import sys

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

def start():
    window = MainWindow()
    window.show()
if __name__ == "__main__":
    app = QApplication(sys.argv)
    start()
    sys.exit(app.exec_())

Doing it this way, and everything is OK:

#!/usr/bin/env python2
# -*- coding: utf-8 -*-

from pomocni import Ui_MainWindow
from PyQt4.QtGui import QMainWindow, QApplication
from PyQt4 import QtCore
import sys

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

What am I doing wrong?

Dani AI

Generated

The first snippet creates a top-level window inside start() and then drops the last Python reference when start() returns. Since the widget has no parent, the Python wrapper is eligible for GC and the window vanishes. In your second version, window lives at module scope until after app.exec_() returns, so it stays visible. As noted, the fix is to keep a strong reference around for as long as the UI should be on screen.

If this module will be imported by other PyQt apps, expose a factory that returns the window (so the caller can hold it), or keep an internal registry. Also, do not spin a new event loop from the module; let the host app own the single QApplication and its exec_(). When debugging the module standalone, only create the app and call exec_() under if __name__ == "__main__":. If you ever need to integrate with an existing app, use QApplication.instance() to reuse the current application object.

Example module pattern that avoids both GC issues and multiple exec_() calls:

# above_module.py
from PyQt4.QtGui import QMainWindow, QApplication
import sys

_windows = []  # keep strong refs when used as a library

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        # build UI here...

def ensure_app():
    return QApplication.instance() or QApplication(sys.argv)

def create_window(parent=None):
    w = MainWindow(parent)
    w.show()
    _windows.append(w)
    return w

if __name__ == "__main__":
    app = ensure_app()
    w = create_window()
    sys.exit(app.exec_())

Caller usage:

import above_module
w = above_module.create_window()  # keep 'w' alive; no extra exec_() needed

Recommended Answers

All 4 Replies

In the first version, window is a local variable in function start(). It is probably garbage collected when the function exits. You need to keep a pointer to window.

OK. Thanks but the above code is a module and will be called from other pyqt programs on various events. The main function is there only for debuging purposes. So the module code is:

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pomocni import Ui_MainWindow
from PyQt4.QtGui import QMainWindow, QApplication
from PyQt4 import QtCore
import sys
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
def start():
    window = MainWindow()
    window.show()

and this code snippet:

import above_module
above_module.start()

does not work and I can't use a pointer because app.exec_() can not be called multiple times.

The most flexible solution is that the calling code stores the pointer to the window

def start():
    window = MainWindow()
    window.show()
    return window

# in calling code
import above_module
window = above_module.start()

The other solution is that the pointer is stored in above_module. For example

window = None

def start():
    global window
    window = MainWindow()
    window.show()

One drawback of this approach is that window is not automatically garbage collected, and if you want several instances, you'll have to use a container.

Thanks Gribouillis solved.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.