Существует ли общая подсистема уведомления/публикации обновлений для GTK?

Я создаю приложение PyGTK с несколькими виджетами, которые при изменении должны уведомлять другие виджеты об изменении. Я хотел бы избежать такого кода:

def on_entry_color_updated(self, widget):
    self.paint_tools_panel.current_color_pane.update_color()
    self.main_window.status_bar.update_color()
    self.current_tool.get_brush().update_color()

И сделайте что-то вроде этого вместо этого:

def on_entry_color_updated(self, widget):
    self.update_notify('color-changed')

Строка состояния, текущая цветовая панель и текущий инструмент подпишутся на это событие уведомления и будут действовать соответственно. Насколько я могу судить, механизм сигнализации GObject позволяет мне зарегистрировать обратный вызов только для определенного виджета, поэтому каждый объект, который хочет получить уведомление, должен знать об этом виджете.

Предоставляет ли GTK такую ​​систему или я должен создать ее самостоятельно? Разработчики Shotwell, приложения для организации фотографий для GNOME, должны были создать собственный сигнальный механизм, насколько я понимаю их оформите документ правильно. Поиск здесь, на SO, не дал окончательных ответов.

Редактировать:

Объяснение, почему я считаю, что сигнализация GObject — это не то, что мне нужно (или просто часть того, что мне нужно). С GObject мне нужно явно связать объект с другим объектом, например:

emitter.connect('custom-event', receiver.event_handler)

Итак, в моем приложении я должен был бы сделать это:

class ColorPane(gtk.Something):
    def __init__(self, application):
        # init stuff goes here...

        application.color_pallette.connect('color-changed', self.update_color)

    def update_color(self, widget):
        """Show the new color."""
        pass

class StatusBar(gtk.Something):
    def __init__(self, application):
        # init stuff goes here...

        application.color_pallette.connect('color-changed', self.update_color)

    def update_color(self, widget):
        """Show the new color name."""
        pass

class Brush(gtk.Something):
    def __init__(self, application):
        # init stuff goes here...

        application.color_pallette.connect('color-changed', self.update_color)

    def update_color(self, widget):
        """Draw with new color."""
        pass

Другими словами, я должен передать объект приложения или какой-либо другой объект, который знает о color_pallete, другим объектам в моем приложении, чтобы они подключались к сигналам color_pallette. Это тот вид связи, которого я хочу избежать.


person dkobozev    schedule 20.10.2011    source источник


Ответы (2)


Например, вы можете создать собственный подкласс GObject, который предоставляет некоторые пользовательские сигналы. Следующий пример представляет собой слегка адаптированную версию примера, приведенного в связанной статье:

import pygtk
pygtk.require('2.0')
import gobject

class Car(gobject.GObject):

    __gsignals__ = {
        'engine-started': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        'engine-stopped': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
    }

    def __init__(self):
        gobject.GObject.__init__(self)
        self._state = 0

    def start(self):
        if not self._state:
            self._state = 1
            self.emit('engine-started')

    def stop(self):
        if self._state:
            self._state = 0
            self.emit('engine-stopped')


gobject.type_register(Car)

def kill_switch(c):
    def callback(*unused, **ignored):
        c.stop()
    return callback

def on_start(*unused, **ignored):
    print "Started..."

def on_stop(*unused, **ignored):
    print "Stopped..."

some_car = Car()
some_car.connect('engine-started', on_start)
some_car.connect('engine-started', kill_switch(some_car))
some_car.connect('engine-stopped', on_stop)
some_car.start()

Другим подходом может быть использование одного из множества пакетов событий/сигналов, уже имеющихся в PyPI, например:

person Dirk    schedule 20.10.2011

GObjects не обязательно должны быть виджетами. Например, класс вашего приложения может быть GObject, который определяет сигналы, к которым подключаются другие виджеты.

Кроме того, я не думаю, что вы правильно поняли дизайн-документ Shotwell. Мне кажется, что их сигнальная система на 100% является сигнальной системой GObject, только с особыми гарантиями в отношении порядка обработки сигналов. Как они говорят в своем дизайн-документе, такие вещи возможны в простом GObject, но Vala упрощает кодирование по-своему.

person ptomato    schedule 20.10.2011
comment
Я думаю, что сигнализация GObject не подходит для моих целей, потому что требует явного соединения двух объектов. Я обновил свой вопрос, чтобы уточнить. - person dkobozev; 20.10.2011