如何在pygtk中使用相同的小部件两次?

2 投票
4 回答
3018 浏览
提问于 2025-04-15 13:49

这个方法不太好用:

    image_log = gtk.Image()
    image_log.set_from_file("test.png")

    self.out_button = gtk.Button()
    self.out_button.add(image_log)

    self.err_button = gtk.Button()
    self.err_button.add(image_log)

    another_box.pack_start(self.out_button, False)
    another_box.pack_start(self.err_button, False)

问题在于,image_log被用了两次,而GTK不喜欢这样。有没有什么.copy()的方法?还是说我应该直接用普通的deepcopy?

补充:看起来在GTK中没有默认的方法来复制对象。在这种情况下,使用工厂方法可以解决这个问题。

GTK的警告:

app/gui.py:248: GtkWarning: gtk_box_pack: assertion `child->parent == NULL' failed
hbox_errlog.pack_start(image_log)

4 个回答

1

为什么不呢

image_log = gtk.Image()
image_log.set_from_file("test.png")
image_logb = gtk.Image()
image_logb.set_from_file("test.png")

self.out_button = gtk.Button()
self.out_button.add(image_log)

self.err_button = gtk.Button()
self.err_button.add(image_logb)

another_box.pack_start(self.out_button, False)
another_box.pack_start(self.err_button, False)

这只多了两行代码,可能比复制第一个图像对象更有效率。

这样你就可以独立处理 out_buttonerr_button。不过,用同一个 gtk.Image() 对象来给两个按钮用也是合理的……毕竟它们只是同一张图片。

编辑 为了避免重复(虽然这看起来有点多余),你可以为相同图片创建一个 gtk.Image() 对象的工厂。

def gtkimage_factory(num_objs, image_file):
    i=0
    imglist = []
    while i<num_objs:
        img_ob = gtk.Image()
        img_ob.set_from_file(image_file)
        imglist.append( img_ob )
        i+=1
    return imglist

或者类似的东西,你明白我的意思。不过,除非你需要大量这样的东西,并且需要它们在 GTK 中独立管理,否则工厂的做法似乎有点过头了。

然后……

image_list = gtkimg_factory(2, "test.png")

self.out_button = gtk.Button()
self.out_button.add(image_list[0])

self.err_button = gtk.Button()
self.err_button.add(image_list[1])

another_box.pack_start(self.out_button, False)
another_box.pack_start(self.err_button, False)

也许这和 GTK 的资源管理有关?

2

使用

def clone_widget(widget):
    widget2=widget.__class__()
    for prop in dir(widget):
        if prop.startswith("set_") and prop not in ["set_buffer"]:
            prop_value=None
                try:
                    prop_value=getattr(widget, prop.replace("set_","get_") )()
                except:
                    try:
                        prop_value=getattr(widget, prop.replace("set_","") )
                    except:
                        continue
                if prop_value == None:
                    continue
                try:
                    getattr(widget2, prop)( prop_value ) 
                except:
                    pass
return widget2

这些“尝试...异常”块的存在是因为并不是所有的属性都可以通过使用 set_prop(get_prop) 来复制。我还没有对所有的属性和小部件进行测试,但它在 gtkEntry 上运行得很好。可能这样做会比较慢,但使用起来还是挺不错的 :)

2

你可以使用工厂函数来减少代码重复

def make_image_from_file(fname):
  im = gtk.Image()
  im.set_from_file(fname)
  return im

self.out_button.set_image(make_image_from_file(..))

重新审视

其实有一种更自然的方法。你一定会喜欢的。在 PyGTK 2.12 及以上版本中:

gtk.image_new_from_file(filename)

我心里有个声音在告诉我这个,但我没有去查证。

http://www.pygtk.org/docs/pygtk/class-gtkimage.html#function-gtk--image-new-from-file

撰写回答