Reputation: 2570
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)
Upvotes: 3
Views: 1445
Reputation:
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!
Upvotes: 2