views:

319

answers:

2

This doesn't work well:

    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)

The problem is, image_log is used twice and GTK doesn't like it. Is there some .copy() method? Or should I just use plain vanilla deepcopy?

EDIT: Looks like there is no default way to clone objects in GTK. Factory will do the trick in this case.

GTK warning:

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

Why not

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)

It is only an extra 2 lines of code, and maybe more efficient than cloning/copying the first image object.

That way you can treat out_button and err_button independently. But it should make sense to use the same gtk.Image() object for both buttons ... it is just an image.

Edit To avoid duplication (seems like overkill though) you could write a factory for gtk.Image() objects from the same 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

Or something along those lines, you get the idea. But a factory seems like overkill unless you are producing loads of these things and need them independently parented in GTK. Then...

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)

Maybe it is something to do with GTK resource management?

Aiden Bell
I am using this approach atm, but duplicating code is what I've always been avoiding. The problem sits because GTK sets parent to each widget (which can only be one).
iElectric
Ah I see. Even though the code is duplication, they are required to be separate instances of gtk.Image() ... so it isn't really duplication. I added an edit.
Aiden Bell
gtk.Image is not just an image. It's a widget displaying an image.
kaizer.se
@kaiser.se - Yup, that is what I meant. Didn't realize single parentage was enforced on all widgets.
Aiden Bell
+1  A: 

You could use a factory function to reduce code duplication

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

Revisiting

There is a much more natural way. You will like it. In PyGTK 2.12+:

gtk.image_new_from_file(filename)

I had something in the back of my mind telling me this, but I didn't look it up.

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

kaizer.se
*shakes fist* :) ... Nice and concise.
Aiden Bell
Thanks kaizer.se! I knew there must be a straight forward way!
iElectric