문제

우선, 나는 경험이 풍부한 C 프로그래머이지만 Python을 처음 사용합니다. PYQT를 사용하여 Python에서 간단한 응용 프로그램을 만들고 싶습니다. 이 응용 프로그램이 실행될 때 단순하다고 상상해 봅시다. 시스템 트레이에 아이콘을 넣어야하며 응용 프로그램을 종료 할 수있는 메뉴에 옵션이 제공됩니다.

이 코드는 작동하고 메뉴를 보여줍니다 (출구 조치를 연결하지 않고 간단하게 유지하기 위해).

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

그러나 이것은 그렇지 않습니다.

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

아마 뭔가 그리워요. 오류는 없지만 두 번째 경우 오른쪽 버튼으로 클릭하면 메뉴가 표시되지 않습니다.

도움이 되었습니까?

해결책

글쎄, 약간의 디버깅 후 나는 문제를 발견했다. Qmenu 객체는 마무리 후 파괴됩니다 __init__ 부모가 없기 때문에 기능합니다. qsystemtrayicon의 부모는 Qmenu의 대상이 될 수 있지만 Qwidget이어야합니다. 이 코드는 작동합니다 (Qmenu가 QWIDGET 인 QSYSTEMTRAYICON과 동일한 부모를 얻는 방법 참조 : :

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

다른 팁

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

EXIT 조치가 구현 된 코드는 다음과 같습니다

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

다음은 pyqt5 버전입니다 (Demosthenes의 답변의 출구 동작을 구현할 수있었습니다).원천 pyqt4에서 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)

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

PYQT5 (시스템 트레이 메뉴의 출구, 실제로 종료되지는 않을 것임)에서 위의 답변을 얻을 수 없었지만 작동하는 솔루션을 위해이를 결합했습니다. 나는 아직도 종료가 어떻게 든 더 사용되어야하는지 결정하려고 노력하고 있습니다.

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)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top