Question

When the following code runs, the tray application can pop-up the AboutWindow QLabel object in the middle of screen. But when closing this screen, the whole application is shutdown with no errors (the tray icon disappears and the console log shows no error whatsoever).

import sys
from PyQt4 import QtGui, QtCore


class AboutWindow(QtGui.QLabel):

def __init__(self, parent=None):
    QtGui.QLabel.__init__(self, parent=parent)
    self.setText("""
    Huge text goes here
    """)


class SystemTrayIcon(QtGui.QSystemTrayIcon):
    def __init__(self, icon, parent=None):
        QtGui.QSystemTrayIcon.__init__(self, icon, parent)
        menu = QtGui.QMenu(parent)
        self.createMenuActions(menu)
        self.setContextMenu(menu)
        # I've tried using the same parent as QSystemTrayIcon, 
        # but the label is not shown.
        # self.aboutWindow = AboutWindow(parent=parent)
        self.aboutWindow = AboutWindow(parent=None)


    def createMenuActions(self, menu):
        exitAction = QtGui.QAction("Exit", menu)
        configureAppAction = QtGui.QAction("Configure Application", menu)
        aboutAction = QtGui.QAction("About", menu)

        self.connect(configureAppAction, QtCore.SIGNAL('triggered()'), self._configureApp)
        self.connect(aboutAction, QtCore.SIGNAL('triggered()'), self._showAbout)
        self.connect(exitAction, QtCore.SIGNAL('triggered()'), self._exitApp)

        self.addActionsToMenu(menu, configureAppAction, aboutAction, exitAction)

    def addActionsToMenu(self, menu, *args):
        for action in args:
            menu.addAction(action)

    def _configureApp(self): pass

    def _showAbout(self):
        self.aboutWindow.show()

    def _exitApp(self):
        sys.exit(0)

def main():
    app = QtGui.QApplication(sys.argv)
    widget = QtGui.QWidget()
    # I'm passing a widget parent to QSystemTrayIcon as pointed out in:
    # http://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application
    trayIcon = SystemTrayIcon(QtGui.QIcon("icon.xpm"), widget)
    trayIcon.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

As pointed out in the code, I've tried setting the same parent for the tray icon and the AboutWindow object, but that didn't work (the label is not shown). I have also tried subclassing QMainWindow, but the same effect occured.

I would like to understand if that's the default behavior when opening a new window from QSystemTrayIcon when neither the window and the icon share the same parent, and if there's a workaround for this matter.

Thanks.

Was it helpful?

Solution

Alright, I guess I wasn't too clear about the problem, but I found a simple solution.

Qt has a method that captures the close event dispatched to a widget (http://doc.qt.nokia.com/4.6/qwidget.html#closeEvent). You can, in your QWidget subclass, rewrite this method to prevent the widget from closing (which, in all my tests, would close the whole application) and only hide it. The code below shows what I've changed in my code to make it work:

...

class AboutWindow(QtGui.QLabel):

    def __init__(self, parent=None):
        QtGui.QLabel.__init__(self, parent=parent)
        self.setText("""
        Huge text goes here
        """)

    # Prevent the widget from closing the whole application, only hides it
    def closeEvent(self, event):
        event.ignore()
        self.hide()

...

OTHER TIPS

This problem occurs because when you close the 'only' window, Qt erroneously thinks you want to quit the application. Your (Kaos12) answer is an ugly fix imho, sometimes you really want to close the stuff (which isn't the same as hiding it). The proper way to do that is to disable this behaviour by adding the line:

app.setQuitOnLastWindowClosed(False)

after the line 50 in that code (after 'creating' the application). This instruction will tell Qt not to quit the application even when all the windows are closed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top