3

I am trying to create a custom widget with PyGObject. For example I want to create this CustomButton widget which adds an image and a label in a button (it's just for the example) :

#!/usr/bin/python
#-*- coding: utf-8 -*

from gi.repository import Gtk

class ImageButton(Gtk.Widget):

    def __init__(self, label, image):
        Gtk.Widget.__init__(self)

        self.hbox = Gtk.HBox()
        self.label = Gtk.Label(label)
        self.image = Gtk.Image.new_from_stock(image, Gtk.IconSize.MENU)

        self.hbox.pack_start(self.image, False, False, 3)
        self.hbox.pack_start(self.label, False, False, 3)

        self.button = Gtk.Button()
        self.button.add(self.hbox)

In another file or class, I can use it like that :

button = ImageButton("My label", Gtk.STOCK_HOME)

But when I want to use it, I am obliged to call the button attribute, like this :

# Connect the "clicked" event 
button.button.connect("clicked", on_clicked_button)

# Add the button in a container
window.add(button.button)

It works but it is not practical. How to create a custom widget working like any other widget please :

button = ImageButton("My label", Gtk.STOCK_HOME)
button.connect("clicked", on_clicked_button)
window.add(button)
9
  • Why can't you just write button.button? Commented Jun 13, 2014 at 9:42
  • It's possible but I want to create a real custom widget. I don't want to write button.button.connect("clicked", on_clicked_button), but just button.connect("clicked", on_clicked_button) Commented Jun 13, 2014 at 9:45
  • So write a connect method... Commented Jun 13, 2014 at 9:46
  • I don't really understand why you have a button attribute and inherit from Button, though. Commented Jun 13, 2014 at 9:47
  • I have a button attribute and inherit from Button because I thought it was a good solution, but if you have the answer I take it :) Commented Jun 13, 2014 at 9:53

1 Answer 1

2

I think that your problem it is actually a problem about understanding classes more then inheritance. If you want your widget to act exactly as a button, it should be a button.

Take a look to the following example:

from gi.repository import Gtk

class ImageButton(Gtk.EventBox):

    def __init__(self, label):

        Gtk.EventBox.__init__(self)
        self.label = Gtk.Label(label)
        self.add(self.label)    


if __name__ == '__main__':
    def on_imagebutton_clicked(button, data=None):
        print("Button has been clicked!")

    window = Gtk.Window()
    button = ImageButton("My label")
    button.connect('button-press-event', on_imagebutton_clicked)
    window.add(button)
    window.show_all()
    Gtk.main()

Instead of saying that my class it is a Gtk.Widget, I said that it is a Gtk.EventBox and I started it like it. From now on ImageButton will have the same attributes and methods like an Gtk.EventBox.

*If I've made the same example by using Gtk.Button instead of a Gtk.EventBox you could call button.connect(.. instead of buton.connect.connect(.. as you want it in your question. The problem with this is that if ImageButton it is a Gtk.Button It is not any more possible of modifying it to do things that buttons don't do ( like adding containers and labels).

In a Few Words:

You can create a custom widget based in other widget, but only one widget will be at the top of the tree.

--> Parent  
---------> Child
---------> Child

So when you do self.method it will always look to:

1) Your parent methods (the one you copied by using Gtk.EventBox.__init__(self)

2) The methods you created.

Alternatively you can lie thanks to this:

from gi.repository import Gtk

class ImageButton(Gtk.EventBox):

    def __init__(self, label):

        Gtk.EventBox.__init__(self)
        self.label = Gtk.Label(label)
        self.add(self.label)    

    def set_text(self, text):
        self.label.set_text(text)

if __name__ == '__main__':
    def on_imagebutton_clicked(button, data=None):
        print("Button has been clicked!")

    window = Gtk.Window()
    button = ImageButton("My label")
    button.connect('button-press-event', on_imagebutton_clicked)
    button.set_text('New text!!')
    window.add(button)
    window.show_all()
    Gtk.main()

Note that I didn't had to call button.label.set_text(..) I hope it be clear enough!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.