Overriding virtual methods in PyGObject
Asked Answered
K

1

6

I'm trying to implement the Heigh-for-width Geometry Management in GTK with Python for my custom Widget. My widget is a subclass from Gtk.DrawingArea and draws some parts of an Image.

As I understood the GTK Docs (link above) I have to implement the following 4 methods:

  • GtkWidgetClass.get_preferred_width()
  • GtkWidgetClass.get_preferred_height()
  • GtkWidgetClass.get_preferred_height_for_width()
  • GtkWidgetClass.get_preferred_width_for_height()

Now wondering where to implement this in Python.

I tried this:

from gi.repository import Gtk
class Patch(Gtk.DrawingArea):
  def __init__(self, model, image, position):
    super(Patch,self).__init__()
    #…

  def get_preferred_width(self, *args, **kargs):
    print("test")

  def get_preferred_height(self, *args, **kargs):
    print("test")

  def get_preferred_width_for_height(self, *args, **kargs):
    print("test")

  def get_preferred_height_for_width(self, *args, **kargs):
    print("test")

But the methods don't get called. In C you define the functions and set it to the widget like this:

static void
my_widget_get_preferred_height (GtkWidget *widget, gint *minimal_height,
                                gint *natural_height)
{
  /* ... */
}
  /* ... */

static void
my_widget_class_init (MyWidgetClass *class)
{
  /* ... */
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
  widget_class->get_preferred_height = my_widget_get_preferred_height;
  /* ... */
}

How is this done in Python?

Konyn answered 29/2, 2012 at 9:14 Comment(4)
Note that pyGObject has been deprecated in favor of GObject-Introspection.Maladjusted
Isn't PyGObject the way to use GObject-Introspection with Python? Did you mean PyGTK is deprecated in favor of PyGObject?Konyn
@liberforce: Confusingly, the Python implementation of GObject Introspection is also called PyGObject. It was called PyGI for a while, but this seems to be the official name now. The old PyGObject was part of PyGTK which is now deprecated. (But the way of overriding virtual methods was the same, I believe.)Tellurium
@ptomato: Wow, you're right: live.gnome.org/PyGI ! Thanks for the tip, I wasn't aware of that.Maladjusted
T
7

You have to name the methods like do_virtual_method:

from gi.repository import Gtk
class Patch(Gtk.DrawingArea):
  def __init__(self):
    super(Patch,self).__init__()

  def do_get_preferred_width(self):
    print("test")
    return 100, 100

  def do_get_preferred_height(self):
    print("test")
    return 100, 100

win = Gtk.Window()
win.add(Patch())
win.connect('destroy', Gtk.main_quit)
win.show_all()
Gtk.main()

Note that you also have to return the values that the virtual method requires you to return, otherwise you'll get a cryptic error.

Tellurium answered 29/2, 2012 at 12:21 Comment(2)
To implement the Height-for-width you must actually override do_get_request_mode, do_get_preferred_height, do_get_preferred_width, do_get_preferred_width_for_height and do_get_preferred_height_for_widthKonyn
Perhaps a little late to the party. How would one chain up to the parent, I would like to call super().do_get_preferred_width(self)? I have a virtual function that breaks the parent, if you don't chain up to the parent. Much like in C GObjects, if you override GObjectClass->finalize, you have to make sure to chainup to the parents class finalize?Duplicator

© 2022 - 2024 — McMap. All rights reserved.