2009-05-21 34 views
22

En primer lugar, soy un programador de C experimentado pero nuevo en python. Quiero crear una aplicación simple en python usando pyqt. Imaginemos que esta aplicación es tan simple como cuando se ejecuta tiene que poner un ícono en la bandeja del sistema y tiene una opción en su menú para salir de la aplicación.PyQt: Mostrar menú en una aplicación de bandeja de sistema

funciona este código, se muestra el menú (no me conecto la acción de salida y así sucesivamente hasta que sea sencillo)

import sys 
from PyQt4 import QtGui 

def main(): 
    app = QtGui.QApplication(sys.argv) 

    trayIcon = QtGui.QSystemTrayIcon(QtGui.QIcon("Bomb.xpm"), app) 
    menu = QtGui.QMenu() 
    exitAction = menu.addAction("Exit") 
    trayIcon.setContextMenu(menu) 

    trayIcon.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

pero esto no significa:

import sys 
from PyQt4 import QtGui 

class SystemTrayIcon(QtGui.QSystemTrayIcon): 

    def __init__(self, icon, parent=None): 
     QtGui.QSystemTrayIcon.__init__(self, icon, parent) 
     menu = QtGui.QMenu() 
     exitAction = menu.addAction("Exit") 
     self.setContextMenu(menu) 

def main(): 
    app = QtGui.QApplication(sys.argv) 

    trayIcon = SystemTrayIcon(QtGui.QIcon("Bomb.xpm"), app) 

    trayIcon.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

I Probablemente te pierdas algo. No hay errores, pero en el segundo caso, cuando hago clic con el botón derecho, no se muestra el menú.

+2

Como programador de C compañero acaba de entrar en Python. Puedo decir "errrmmm" también. –

+0

Si su respuesta resuelve el problema, elija la copia de la wiki de la comunidad de su respuesta como "la" respuesta (no obtendré ninguna reputación :). También edité tu respuesta para corregir un error tipográfico menor. – tzot

Respuesta

26

Bueno, después de algunas depuraciones encontré el problema. El objeto QMenu se destruye después de finalizar la función __init__ porque no tiene un elemento principal. Mientras que el padre de un QSystemTrayIcon puede ser un objeto para el QMenu, tiene que ser un Qwidget. Este código funciona (ver cómo QMenu obtiene el mismo padre que el QSystemTrayIcon que es un QWidget):

import sys 
from PyQt4 import QtGui 

class SystemTrayIcon(QtGui.QSystemTrayIcon): 

    def __init__(self, icon, parent=None): 
     QtGui.QSystemTrayIcon.__init__(self, icon, parent) 
     menu = QtGui.QMenu(parent) 
     exitAction = menu.addAction("Exit") 
     self.setContextMenu(menu) 

def main(): 
    app = QtGui.QApplication(sys.argv) 

    w = QtGui.QWidget() 
    trayIcon = SystemTrayIcon(QtGui.QIcon("Bomb.xpm"), w) 

    trayIcon.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 
7

Creo que preferiría el siguiente, ya que no parece depender de las decisiones internas de recolección de basura de QT.

import sys 
from PyQt4 import QtGui 

class SystemTrayIcon(QtGui.QSystemTrayIcon): 
    def __init__(self, icon, parent=None): 
     QtGui.QSystemTrayIcon.__init__(self, icon, parent) 
     self.menu = QtGui.QMenu(parent) 
     exitAction = self.menu.addAction("Exit") 
     self.setContextMenu(self.menu) 

def main(): 
    app = QtGui.QApplication(sys.argv) 
    style = app.style() 
    icon = QtGui.QIcon(style.standardPixmap(QtGui.QStyle.SP_FileIcon)) 
    trayIcon = SystemTrayIcon(icon) 

    trayIcon.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 
+0

¿por qué aparece en la barra del dock en Mac OSx? –

+0

Wow, ¿entonces esta no es la bandeja del sistema? – fatuhoku

3

Este es el código con la acción Salir implementado

import sys 
from PyQt4 import QtGui, QtCore 

class SystemTrayIcon(QtGui.QSystemTrayIcon): 
    def __init__(self, icon, parent=None): 
     QtGui.QSystemTrayIcon.__init__(self, icon, parent) 
     menu = QtGui.QMenu(parent) 
     exitAction = menu.addAction("Exit") 
     self.setContextMenu(menu) 
     QtCore.QObject.connect(exitAction,QtCore.SIGNAL('triggered()'), self.exit) 

    def exit(self): 
     QtCore.QCoreApplication.exit() 

def main(): 
    app = QtGui.QApplication(sys.argv) 

    w = QtGui.QWidget() 
    trayIcon = SystemTrayIcon(QtGui.QIcon("qtLogo.png"), w) 

    trayIcon.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 
+0

Nota *: debe tener la imagen qtLogo.png en el mismo directorio con la secuencia de comandos – demosthenes

0

Aquí está la versión PyQt5 (era capaz de poner en práctica la acción de salida de la respuesta de demóstenes). Source para portar desde PyQt4 a PyQt5

import sys 
from PyQt5 import QtCore, QtGui, QtWidgets 
# code source: https://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application - add answer PyQt5 
#PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui 
class SystemTrayIcon(QtWidgets.QSystemTrayIcon): 

    def __init__(self, icon, parent=None): 
     QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) 
     menu = QtWidgets.QMenu(parent) 
     exitAction = menu.addAction("Exit") 
     self.setContextMenu(menu) 

def main(image): 
    app = QtWidgets.QApplication(sys.argv) 

    w = QtWidgets.QWidget() 
    trayIcon = SystemTrayIcon(QtGui.QIcon(image), w) 

    trayIcon.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    on=r''# ADD PATH OF YOUR ICON HERE .png works 
    main(on) 
0

Con un evento conectado pyqt5:

class SystemTrayIcon(QtWidgets.QSystemTrayIcon): 

    def __init__(self, icon, parent=None): 
     QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) 
     menu = QtWidgets.QMenu(parent) 
     exitAction = menu.addAction("Exit") 
     self.setContextMenu(menu)  
     menu.triggered.connect(self.exit) 

    def exit(self): 
     QtCore.QCoreApplication.exit() 
Cuestiones relacionadas