Существует ли общая подсистема уведомлений об обновлениях / паб для GTK? - PullRequest
1 голос
/ 20 октября 2011

Я создаю приложение 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, должны были создать свой собственный механизм сигнализации, если я правильно понимаю их design doc .Поиск здесь на 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.Это тот тип соединения, которого я хочу избежать.

Ответы [ 2 ]

1 голос
/ 20 октября 2011

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

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

1 голос
/ 20 октября 2011

Например, вы можете создать пользовательский подкласс 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, например:

...