我正在构建一个带有几个小部件的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使其更容易以他们的方式进行编码。