I try to create a proper container Class for Gtk in Python (MyBin
in the code below). There seems to be no authoritative documentation on how to do that, only bits and pieces, which I glued together with trial and error. – There are many open questions, but let me focus on size_allocate()
here:
What is the the original size_allocate()
function doing? And what is my overlaid version in my container class supposed to do?
I already do 95% know that I have to replace the original method with my own by prepending “do_” to form the do_size_allocate()
method (by trial and error – see code below; I could not find anything talking about all those “do_*” functions).
I found so far, that calling self.set_allocation(allocation)
seems to be a good idea as is self.get_child().size_allocate(...)
to give the child some working space (see code). – Any other obligations I have to fulfill? What is the original function doing additionally?
Regarding the allocation I pass down to the child: I need to adapt it (not in the code below yet). I successfully(?) used a fresh Gdk.Rectangle()
on which I set x, y, width and height, but I somehow feel that it’s wrong and something with (do_)adjust_size_allocation()
should be used instead. But how?
Lets look into the documentation of do_size_allocate()
:
This function is only used by Gtk.Container subclasses, to assign a size and position to their child widgets. [“Only used”? Only called from? Only implemented at? Only overwritten by? – Well, I’m doing it already, but the doc wasn’t helpful in finding out how.]
In this function, the allocation may be adjusted. [How?] It will be forced to a 1x1 minimum size [Can confirm only that
get_allocation()
will return a 1x1 if I don’t set anything.],and the adjust_size_allocation virtual method on the child will be used to adjust the allocation. [What? For my own allocation? Or for the one I set on the child via...get_child().size_allocate()
? Who calls that adjust method? In which conditions is it not called beforesize_allocate()
?] Standard adjustments include removing the widget’s margins, and applying the widget’s Gtk.Widget :halign and Gtk.Widget :valign properties.
#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class MyBin(Gtk.Bin):
def __init__(self):
super().__init__()
def do_size_allocate(self, allocation):
print('PARENT METHOD do_size_allocate', allocation.width)
# if not called, `get_allocation()` in `do_draw()` will return a 1x1 rectangle
self.set_allocation(allocation)
# strangely required so that `do_draw()` will be called even on this class!
self.get_child().size_allocate(allocation)
def do_draw(self, c):
allocation = self.get_allocation()
print('PARENT do_draw()', allocation.width)
self.propagate_draw(self.get_child(), c)
class MyChild(Gtk.Button):
def __init__(self):
super().__init__()
self.connect('size-allocate', self.size_allocate_handler)
self.connect('draw', self.draw_handler)
def size_allocate_handler(self, self2, allocation):
print('CHILD signal size-allocate', allocation.width)
def draw_handler(self, self2, c):
allocation = self.get_allocation()
print('CHILD signal draw', allocation.width)
class MainWindow(Gtk.Window):
def __init__(self):
super().__init__(title='d2see test pattern')
the_child = MyChild()
my_container = MyBin()
my_container.add(the_child)
self.add(my_container)
self.show_all()
if __name__ == '__main__':
MainWindow()
Gtk.main()