PyQt4 Tray Icon Problem when showing QLabel
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.
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()
...
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.
精彩评论