是否有GTK的通用更新通知/ pub子系统?

时间:2011-10-20 15:22:19

标签: python user-interface architecture gtk pygtk

我正在构建一个包含多个小部件的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是否提供这样的系统,还是应该自己构建?如果我了解他们的{{3},那么GNOME照片组织应用程序Shotwell的开发人员必须建立自己的信令机制。正确的。在这里搜索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 个答案:

答案 0 :(得分:1)

首先,您可以创建GObject的自定义子类,其中提供了一些custom signals。以下示例是链接文章中给出的稍微改编的版本:

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上已有的众多事件/信令包之一,例如:

答案 1 :(得分:1)

GObjects不一定是小部件。例如,您的应用程序类可以是GObject,它定义其他小部件连接的信号。

另外,我认为您没有正确理解Shotwell设计文档。在我看来,他们的信号系统是100%GObject信号系统,只是特别保证信号的处理顺序。正如他们在设计文档中所说的那样,在简单的GObject中这样的事情是可能的,但Vala使得用它们编写代码变得更容易。