Создать собственный виджет с PyGObject
Я пытаюсь создать собственный виджет с PyGObject. Например я хочу создать это CustomButton
виджет, который добавляет изображение и метку в кнопку (это только для примера):
#!/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)
В другом файле или классе я могу использовать его так:
button = ImageButton("My label", Gtk.STOCK_HOME)
Но когда я хочу использовать это, я обязан позвонить button
атрибут, как это:
# Connect the "clicked" event
button.button.connect("clicked", on_clicked_button)
# Add the button in a container
window.add(button.button)
Это работает, но это не практично. Как создать собственный виджет, работающий как любой другой виджет, пожалуйста:
button = ImageButton("My label", Gtk.STOCK_HOME)
button.connect("clicked", on_clicked_button)
window.add(button)
1 ответ
Я думаю, что ваша проблема - это проблема понимания классов, а не наследования. Если вы хотите, чтобы ваш виджет действовал как кнопка, это должна быть кнопка.
Посмотрите на следующий пример:
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()
Вместо того, чтобы говорить, что мой класс это Gtk.Widget
Я сказал, что это Gtk.EventBox
и я начал это так. Впредь ImageButton
будет иметь такие же атрибуты и методы, как Gtk.EventBox
,
* Если я сделал тот же пример, используя Gtk.Button
вместо Gtk.EventBox
ты можешь позвонить button.connect(..
вместо buton.connect.connect(..
как ты хочешь в своем вопросе. Проблема в том, что если ImageButton
это Gtk.Button
Больше невозможно изменить его так, чтобы он делал то, чего не делают кнопки (например, добавляя контейнеры и метки).
В нескольких словах:
Вы можете создать собственный виджет, основанный на другом виджете, но только один виджет будет в верхней части дерева.
--> Parent
---------> Child
---------> Child
Итак, когда вы делаете self.method
это всегда будет выглядеть так:
1) Ваши родительские методы (тот, который вы скопировали с помощью Gtk.EventBox.__init__(self)
2) Методы, которые вы создали.
В качестве альтернативы вы можете лгать благодаря этому:
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()
Обратите внимание, что мне не пришлось звонить button.label.set_text(..)
Я надеюсь, что это будет достаточно ясно!