GTK 是否有通用更新通知/发布子系统?

发布于 2024-12-10 18:20:23 字数 1908 浏览 1 评论 0原文

我正在构建一个带有多个小部件的 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 信号。这是我想要避免的耦合。

I'm building a PyGTK application with several widgets that when changed, need to notify other widgets about the change. I would like to avoid code like this:

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()

And do something like this instead:

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

The status bar, current color pane and current tool would subscribe to that notification event and act accordingly. From what I can tell, the GObject signaling mechanism only allows me to register a callback on a particular widget, so each object that wants to receive a notification has to be aware of that widget.

Does GTK provide such a system or should I build it myself? Developers of Shotwell, a photo organization application for GNOME, had to build their own signaling mechanism, if I understand their design doc correctly. Searching here on SO didn't turn out any definitive answers.

Edit:

Clarification why I think GObject signaling is not what I need (or just a part of what I need). With GObject, I need to explicitly connect an object to another object, like so:

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

So in my application, I would have to do this:

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

In other words, I have to pass the application object or some other object that knows about the color_pallete to other objects in my application so that they connect to color_pallette signals. This is the kind of coupling that I want to avoid.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陪你到最终 2024-12-17 18:20:23

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

For one, you could create a custom subclass of GObject, which provides some custom signals. The following example is a slightly adapted version of the one given in the linked article:

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()

Another approach would be to take advantage of one of the many event/signalling packages already on PyPI, for example:

箹锭⒈辈孓 2024-12-17 18:20:23

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

另外,我认为您没有正确理解 Shotwell 设计文档。在我看来,他们的信号系统是 100% GObject 信号系统,只是对信号处理的顺序有特殊的保证。正如他们在设计文档中所说,这些事情在普通的 GObject 中是可能的,但 Vala 使按照他们的方式编码变得更容易。

GObjects don't have to be widgets. For example, your application class can be a GObject which defines signals that other widgets connect to.

Also, I don't think you understood the Shotwell design document correctly. It looks to me like their signalling system is 100% GObject signalling system, just with particular guarantees about the order in which signals are handled. As they say in their design document, such things are possible in plain GObject, but Vala makes it easier to code it their way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文