2009-05-21 9 views
22

Po pierwsze, jestem doświadczonym programistą C, ale nowym w Pythonie. Chcę utworzyć prostą aplikację w Pythonie za pomocą pyqt. Wyobraźmy sobie, że ta aplikacja jest tak prosta, jak wtedy, gdy jest uruchomiona, musi umieścić ikonę w zasobniku systemowym i ma opcję w swoim menu, aby opuścić aplikację.PyQt: Pokaż menu w zasobniku systemowym

Ten kod działa, pokazuje menu (nie łączyć działania wyjścia i tak dalej keep it 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() 

Ale tego nie robi:

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 prawdopodobnie tęsknię za czymś. Nie ma błędów, ale w drugim przypadku kliknięcia prawym przyciskiem nie wyświetlają menu.

+2

Jako programista C kolegi tylko uzyskiwanie w Pythonie. Mogę też powiedzieć "errrmmm". –

+0

Jeśli twoja odpowiedź rozwiązuje problem, wybierz kopię społeczności-wiki swojej odpowiedzi jako "odpowiedź" (nie dostanę żadnej reputacji :). Zmieniłem też twoją odpowiedź, by naprawić pomniejszą literówkę. – tzot

Odpowiedz

26

Po pewnym debugowaniu znalazłem problem. Obiekt QMenu został zniszczony po zakończeniu funkcji __init__, ponieważ nie ma elementu nadrzędnego. Podczas gdy rodzicem QSystemTrayIcon może być obiekt dla QMenu, musi to być Qwidget. Ten kod działa (zobacz jak QMenu dostaje tego samego rodzica jako QSystemTrayIcon który jest 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

myślę wolałbym następujące gdyż nie wydaje się zależeć od wewnętrznych decyzji zbiórki śmieci 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

dlaczego pojawia się na pasku dokowania w systemie Mac OSx? –

+0

Wow, więc to nie jest w ogóle tacka systemowa? – fatuhoku

3

Oto kod z działaniem Exit realizowane

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

Uwaga *: Musisz mieć obraz qtLogo.png w tym samym katalogu ze skryptem – demosthenes

0

Oto wersja PyQt5 (był w stanie realizować działania wyjściu odpowiedź Demostenes męska). Source za przeniesienie z PyQt4 do 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

Przy podłączonym imprezy 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()