Страницы

Поиск по вопросам

среда, 25 декабря 2019 г.

Как организовать приложение на PyQt, работающее в трее?

#python #pyqt4


Есть код:  

import os
import sys
import types

from collections import OrderedDict
from PyQt4 import QtGui

class SetTrayIcon(QtGui.QSystemTrayIcon):

    def __init__(self, icon, parent=None):
        self.icon = QtGui.QIcon(QtGui.QPixmap(icon))
        self.parent = parent

        QtGui.QSystemTrayIcon.__init__(self, self.icon, self.parent)
        self.menu = QtGui.QMenu(self.parent)

    def setMenu(self, menu=None):
        """Устанавливает пункты меню на иконке в трее"""

        if not menu:
            menu = []

        # Создаем коллекцию не отсортированых элементов.
        collection = OrderedDict(menu)
        items = collection.keys()  # [имена пунктов]
        functions = collection.values()  # [функции, соотвествующие пунктам]

        for i, item in enumerate(items):
            function = functions[i]
            if isinstance(function, types.MethodType) \
                or isinstance(function, types.FunctionType):
                self.menu.addAction(QtGui.QAction(item, self,
                                    triggered=function))

        self.quitAction = QtGui.QAction("Exit", self,
                                        triggered=QtGui.qApp.quit)
        self.menu.addAction(self.quitAction)

        self.setContextMenu(self.menu)

def show(icon=None, menu=None):
    if not isinstance(icon, str) or not icon or not os.path.isfile(icon):
        raise TypeError, "Parameter 'icon' should be the path to the image"

    app = QtGui.QApplication(sys.argv)
    trayIcon = SetTrayIcon(icon, QtGui.QWidget())

    if menu and isinstance(menu, list):
        trayIcon.setMenu(menu)

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

def item1():
    print "Call function "
def item2():
    print "Call function "

icon = "/home/zavulon/Programming/Projects/Python2.7/FilesInspector/data" \
       "/image/icon.png"
menu = [(u"item1", item1), (u"item2", item2)]
show(icon, menu)

И вот тут мне не понятно: где должен быть основной код приложения, при условии, что
он работает в цикле (программа отслеживает изменения файловой системы), если после
sys.exit(app.exec_()) никаких действий выполнено быть не может - либо интерфейс замораживается
и работает основной код в цикле, либо висит иконка в трее и ничего не происходит? Пробовал
через thread, вылазит ошибка.    


Ответы

Ответ 1



Кому интересно, вот решение моего вопроса: # -*- coding: utf-8 -*- import time import sys import types from collections import OrderedDict from PyQt4 import QtGui, QtCore class ProgramTray(QtCore.QThread): def __init__(self, icon): QtCore.QThread.__init__(self) self.menu = QtGui.QMenu() self.icon = QtGui.QSystemTrayIcon(QtGui.QIcon(icon)) self.flag_exit = True def run(self): """Код работающий в отдельном потоке""" while self.flag_exit: time.sleep(2) print "I'm working ..." QtGui.QApplication.quit() def stop(self): self.flag_exit = False def setMenu(self, menu=None): """Устанавливает пункты меню по клику на иконку в трее""" if not menu: menu = [] # Создаем коллекцию не отсортированых элементов. collection = OrderedDict(menu) items = collection.keys() # [имена пунктов] functions = collection.values() # [функции. соотвествующие пунктам] for i, item in enumerate(items): function = functions[i] if isinstance(function, types.MethodType) \ or isinstance(function, types.FunctionType): self.menu.addAction(QtGui.QAction(item, self, triggered=function)) self.quitAction = QtGui.QAction("Exit", self, triggered=self.stop) self.menu.addAction(self.quitAction) self.icon.setContextMenu(self.menu) app = QtGui.QApplication(sys.argv) program = ProgramTray( "/home/zavulon/Programming/Projects/Python2.7/FilesInspector/data/" "image/icon.png") program.setMenu() program.icon.show() program.start() app.exec_() Иконка висит в трее, программный код выполняется в отдельном потоке.

Комментариев нет:

Отправить комментарий