0
0 комментариев

У меня есть приложение, работающее в трее с использованием PyGTK. Приложение в работает в бесконечном цикле, сканируя файловую систему. Я планирую запустить в отдельном потоке модуль, который устанавливает иконку в трее, в основном же потоке будет работать сам цикл. Но здесь беда — метод gtk.main() блокирует выполнение моего скрипта. То есть поток как бы создается, но дальнейшая работа кода не выполняется. Вот пример:

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
# [SNIPPET_NAME: Systray icon]
# [SNIPPET_CATEGORIES: PyGTK]
# [SNIPPET_DESCRIPTION: Shows a system tray icon with a menu  ]
# [SNIPPET_AUTHOR: João Pinto <joao.pinto@getdeb.net>]
# [SNIPPET_LICENSE: GPL]
#
# Модификация: Иванов Юрий aka HeaTTheatR
# Март, 2015
# Луганск
#
# Email: gleb.assert@mail.ru
# gorodage@gmail.com
#
 
import os
import types
 
from collections import OrderedDict
 
try:
    import pygtk
    pygtk.require("2.0")
    import gtk
except ImportError, exc:
    raise ImportError(
        "Install the library 'gtk' and 'pyGTK'\n{0}".format(str(exc))
    )
 
class SysTrayIconApp:
    """Устанавливает иконку  с пунктами меню в системный трей"""
 
    def __init__(self, label, icon, menu, quit):
        """
        type label: str
        param label: подпись трея
 
        type icon: str
        param icon: путь к иконке
 
        type menu: list
        param menu:[("Подпись кнопки", пользовательская функция))]
 
        type quit: bool
        param quit: если True - будет создан пункт "Quit" с функцией выхода
 
        """
 
        self.tray = gtk.StatusIcon()
 
        if icon is not None and os.path.exists(icon) and os.path.isfile(icon):
            pixbuf = gtk.gdk.pixbuf_new_from_file(icon)
            scaled_buf = pixbuf.scale_simple(24, 24, gtk.gdk.INTERP_BILINEAR)
            self.tray.set_from_pixbuf(scaled_buf)
        else:
            self.tray.set_from_stock(gtk.STOCK_ABOUT)
 
        self.tray.connect('popup-menu', self.on_right_click)
        self.tray.set_tooltip(label)
 
        if not menu:
            menu = [("Quit", gtk.main_quit)]
        if quit:
            menu.append(("Quit", gtk.main_quit))
        self.item_menu = menu
 
    def on_right_click(self, icon, event_button, event_time):
        self.make_menu(event_button, event_time)
 
    def make_menu(self, event_button, event_time):
        menu = gtk.Menu()
 
        # создаем коллекцию не отсортированных элементов
        collection = OrderedDict(self.item_menu)
        items = collection.keys()  # [имена пунктов]
        functions = collection.values()  # [функции, соответствующие пунктам]
 
        for i, name_item in enumerate(items):
            function = functions[i]
            if isinstance(function, types.MethodType) \
                    or isinstance(function, types.FunctionType) \
                    or isinstance(function, types.BuiltinFunctionType):
                    item = gtk.MenuItem(name_item)
                    item.show()
                    menu.append(item)
                    item.connect('activate', function)
 
        menu.popup(None, None, gtk.status_icon_position_menu,
                   event_button, event_time, self.tray)
 
def show(label="", icon=None, menu=None, quit=True):
    SysTrayIconApp(label, icon, menu, quit)
    gtk.main()
 
if __name__ == "__main__":
    import threading
 
    def show_about_dialog(widget=None):
        print "call <show_about_dialog>"
 
    def show_license(widget=None):
        print "call <show_license>"
 
    label = "This is the name of your program's"
    menu = [("About", show_about_dialog), ("License", show_license)]
    icon = "./icon.png"
 
    tray = threading.Thread(target=show, args=(label, icon, menu,))
    tray.run()
 
    # Здесь будет работать цикл while,
    # который будет сканировать файловую систему пользователя.
    print "There is a cycle to work 'while'"


Добавить комментарий