PyGI模拟设置属性/要发出的适当信号?

2024-09-28 17:20:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个现有的项目,我正试图围绕它构建一个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()

当当前代码运行时,单击该按钮不会立即产生结果,但是在更改的行上运行鼠标将导致中心正方形变为红色(因为将鼠标悬停在该行上会触发刷新)。通常,当一个'proper'GObject有一个set_属性被调用时,它会发出一些信号来通知包含它的小部件重新呈现。在

我需要知道是哪个信号发出的,它是向谁发出的,以及如何模仿这种行为。在


Tags: tofromselfgtkmoveobjectvaluemain
1条回答
网友
1楼 · 发布于 2024-09-28 17:20:46

如果您知道必须重新绘制的小部件,那么您可以为该小部件调用queue_draw()queue_draw_region()或{}。这将使窗口区域无效,并将重新绘制。如果您想要更细粒度的控制,您可能需要使用Gtk图纸区域. 在

您可能需要检查文档中的The GTK+ Drawing Model。在

相关问题 更多 >