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_pallette的对象传递给应用程序中的其他对象,以便它们连接到color_pallette信号。这就是我想要避免的那种耦合

首先,您可以创建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上已有的许多事件/信令包之一,例如:

    <
  • Zope事件/gh>
  • 路易
  • PyDispatcher
  • <
  • 飞镖事件/gh>
  • 格子

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

另外,我认为你没有正确理解Shotwell设计文件。在我看来,他们的信号系统是100%的GObject信号系统,只是对信号处理的顺序有特定的保证。正如他们在他们的设计文档中所说的那样,这样的事情在普通对象中是可能的,但是Vala使其更容易以他们的方式进行编码。

最新更新