PYQT: عرض القائمة في تطبيق علبة النظام
-
23-08-2019 - |
سؤال
بادئ ذي بدء، أنا مبرمج ذ ذوي الخبرة ولكن جديد في بيثون. أريد إنشاء تطبيق بسيط في Python باستخدام Pyqt. دعونا نتخيل هذا التطبيق هو بسيط كما هو الحال عندما يتم تشغيله، يجب أن تضع أيقونة في علبة النظام وتقديم خيار في قائمةه للخروج من التطبيق.
يعمل الرمز هذا، إنه يظهر القائمة (لا أقوم بتوصيل إجراء الخروج وما إلى ذلك للحفاظ عليه بسيطا)
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__
وظيفة لأنها لا تملك أحد الوالدين. في حين أن الوالد من QsysterTrayon يمكن أن يكون كائن ل QMENU يجب أن يكون Qwidget. يعمل هذا الرمز (انظر كيف يحصل Qmenu على نفس الوالدين مثل QsySTERTRAYICON وهو 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()
نصائح أخرى
أعتقد أنني أفضل ما يبدو أنه لا يبدو أنه يعتمد على قرارات جمع القمامة الداخلية في 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()
هنا هو الرمز مع تنفيذ إجراء الخروج
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)