asermax
asermax

Reputation: 3133

Extending from GtkBin

I'm trying to make a custom widget that resembles the "quick search" entry that Gtk uses on all TreeView-like widgets.

Here's a simplified example of my initial idea:

from gi.repository import Gtk

class QuickSearch(Gtk.Bin):
    def __init__(self, *args, **kwargs):
        super(QuickSearch, self).__init__(*args, **kwargs)
        self.add(Gtk.Entry())

win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
search = QuickSearch()
win.add(search)
win.show_all()
Gtk.main()

The problems are the following:

So, there's something I'm missing on the object initialization or how I'm using this custom widget? Is this a problem specific to GtkBin? I tried doing the same with a GtkBox and works flawlesly, but I think GtkBin is better suited for this particular widget.

Upvotes: 1

Views: 446

Answers (1)

ptomato
ptomato

Reputation: 57930

For some reason, Gtk.Bin is not allocating space to its child. If you implement the do_size_allocate virtual method then it works. Why the default implementation is not being called, I have no idea.

from gi.repository import Gtk, Gdk

class QuickSearch(Gtk.Bin):
    def __init__(self, *args, **kwargs):
        super(QuickSearch, self).__init__(*args, **kwargs)
        self.add(Gtk.Entry())

    def do_size_allocate(self, allocation):
        self.set_allocation(allocation)
        child_allocation = Gdk.Rectangle()
        border_width = self.get_border_width()
        child_allocation.x = allocation.x + border_width
        child_allocation.y = allocation.y + border_width
        child_allocation.width = allocation.width - 2 * border_width
        child_allocation.height = allocation.height - 2 * border_width
        self.get_child().size_allocate(child_allocation)

win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
search = QuickSearch()
win.add(search)
win.show_all()
Gtk.main()

However, I think inheriting from a Gtk.Frame is more appropriate for your purpose; it is a one-child container with a styleable border around it, which is what you want and more. And its size allocate method works.

Upvotes: 3

Related Questions