PyQt: afficher le menu dans une application de plateau de système

tout d'abord, je suis un programmeur expérimenté en C mais nouveau en python. Je veux créer une application simple en python en utilisant pyqt. Imaginons cette application c'est aussi simple que lorsqu'il est exécuté, il doit mettre une icône dans la barre d'état système et il a proposent une option dans le menu pour quitter l'application.

ce code fonctionne, il affiche le menu (Je ne connecte pas l'action de sortie et ainsi de suite pour le garder simple)

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()

mais ce n'est pas:

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()

quelque chose doit me manquer. Il n'y a pas d'erreurs mais dans le deuxième cas, quand je clique avec le bouton droit qu'il n'affiche pas le menu.

22
demandé sur ROMANIA_engineer 2009-05-21 21:05:35

6 réponses

bien, après quelques déboguages j'ai trouvé le problème. L'objet QMenu est détruit après la fin de la fonction __init__ parce qu'il n'a pas de parent. Alors que le parent D'un QSystemTrayIcon peut être un objet pour le QMenu, il doit être un Qwidget. Ce code fonctionne (voir comment QMenu obtient le même parent que QSystemTrayIcon qui est 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()
26
répondu Nextorlg 2009-05-22 00:37:50

je pense que je préférerais ce qui suit car cela ne semble pas dépendre des décisions internes de Qt en matière de collecte des ordures.

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()
7
répondu Gerard 2010-07-12 17:32:23

voici le code avec action de sortie mise en œuvre

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()
4
répondu demosthenes 2016-10-27 13:49:27

Voici la version PyQt5 (capable de mettre en œuvre l'action de sortie de la réponse de demosthenes). Source pour le portage de PyQt4 à PyQt5

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
# code source: /q/pyqt-show-menu-in-a-system-tray-application-71184/"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)
1
répondu Enora 2017-05-23 12:17:20

avec un événement pyqt5 connecté:

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()
1
répondu Jonathan 2018-02-16 01:29:39

Je ne pouvais obtenir aucune des réponses ci-dessus pour travailler dans PyQt5 (la sortie dans le menu de plateau de système, ne serait pas réellement sortir), mais j'ai réussi à les combiner pour une solution qui fonctionne. J'essaie toujours de déterminer si exitAction doit être utilisé plus loin.

import sys
from PyQt5 import QtWidgets, QtCore, 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)
        menu.triggered.connect(self.exit)

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

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='icon.ico'
    main(on)
0
répondu Roochiedoor 2018-04-17 02:09:24