PyGI模拟set_attribute /发出适当的信号?

时间:2012-09-17 04:09:50

标签: python gtk3 pygobject

我有一个现有的项目,我试图建立一个GUI(使用PyGI + Gtk3)。我需要稍微扩展一些本机对象以使它们可渲染。我已将问题归结为简化代码:

# Simplified Equivalent Code

from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import GdkPixbuf

# Pre-existing, complex object
class Move(object):
    def __init__(self, color):
        self.color = color

# Pre-existing, complex object
class Block(object):
    def __init__(self,move=None,**kwds):
        self.move = move

# New object created to help render a Block
class BlockGui(Block):
    pixbufs = {
            'empty' : GdkPixbuf.Pixbuf.new_from_file('block_empty.png'),
            'red' : GdkPixbuf.Pixbuf.new_from_file('block_red.png'),
            'blue' : GdkPixbuf.Pixbuf.new_from_file('block_blue.png'),
          }

    def __setattr__(self, name, value):
        super(BlockGui, self).__setattr__(name, value)

        if name == 'move':
            print "Need to emit a signal here"

    def get_pixbuf(self):
        try:
            return BlockGui.pixbufs[self.move.color]
        except AttributeError:
            return BlockGui.pixbufs['empty']

class BlockRenderer(Gtk.CellRendererPixbuf):
    __gproperties__ = {
            'block' : (GObject.TYPE_PYOBJECT,
                'block to render',
                'the block object to be rendered',
                GObject.PARAM_READWRITE)
            }

    def __init__(self):
        GObject.GObject.__init__(self)
        self.block = None

    def do_set_property(self, prop, value):
        # What is a GParamBoxed? Should I be checking if prop == 'block' from it somehow?
        if isinstance(value, BlockGui):
            self.block = value
            self.set_property('pixbuf', self.block.get_pixbuf())

GObject.type_register(BlockRenderer)

def destroy(widget, data=None):
    Gtk.main_quit()

# Normally do not have access to this assignment
def on_clicked(widget, liststore, treeview):
    treeiter = liststore.get_iter(2)
    block = liststore.get_value(treeiter, 1)
    block.move = Move('red')

def main():
    # 3x5 so this demo window has some size
    fmt = [GObject.TYPE_PYOBJECT] * 3
    liststore = Gtk.ListStore(*fmt)
    for r in xrange(5):
        liststore.append([BlockGui() for x in xrange(3)])

    treeview = Gtk.TreeView(liststore)

    for c in xrange(3):
        col = Gtk.TreeViewColumn(str(c))
        treeview.append_column(col)
        cell = BlockRenderer()
        col.pack_start(cell, True)
        col.add_attribute(cell, 'block', c)

    button = Gtk.Button("Change Color!")
    button.connect('clicked', on_clicked, liststore, treeview)

    vbox = Gtk.VBox()
    vbox.add(treeview)
    vbox.add(button)

    window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
    window.connect('destroy', destroy)
    window.add(vbox)
    window.show_all()

    Gtk.main()

if __name__ == '__main__':
    main()

当前代码运行时,单击该按钮不会产生立即结果,但在更改的行上运行鼠标将导致中心方块变为红色(因为悬停在该行上会触发刷新)。通常情况下,当一个“正确的”#39; GObject有一个调用的set_attribute,它会发出一些信号来通知包含它的小部件重新渲染。

我需要知道发出的信号,发出的信号,以及如何模仿这种行为。

1 个答案:

答案 0 :(得分:0)

如果您知道必须重新绘制的窗口小部件,则可以为该窗口小部件调用queue_draw()queue_draw_region()queue_draw_area()。这将使该窗口区域无效并将重绘。如果你想要更精细的控制,你可能想要使用Gtk.DrawingArea。

您可能需要查看 The GTK+ Drawing Model 的文档。