Ubuntu – How to dynamically resize GTK notebook pages

application-developmentgtkpygipython

I've got a Python app that uses a Gtk.Notebook widget to display different pages. Each of these pages contain a different set of widgets, and I've noticed that the 'tallest' widget in terms of vertical space defines the overall vertical size of the notebook.

But I'd actually like my app to resize the pages to not waste vertical space, and adapt, that is, get resized to the same vertical size as the widget they contain. This resize should happen when I select each page.

Test app showing undesired vertical space

Here's the sample code to generate this notebook (the example contains a widget per page for the sake of simplicity)

So in short, how can I dynamically resize notebook pages upon selecting them, so that their vertical space is adapted to be the same as their child widget?

Best Answer

I do not know a nice answer, but I have a work-around for you:

The basic idea is that you need a container widget as the parent widget in each page (do not place e.g. a label directly in the page), and you can hide/show everything except the container (If you hide the container as well, the page will disappear).

This solution should work for otherwise arbitrary widget hierarchies.

from gi.repository import Gtk

class NotebookWindow():
    def __init__(self):
        self.builder = Gtk.Builder()
        self.builder.add_from_file('notebook.ui')
        self.builder.get_object('window1').connect('delete-event',
            Gtk.main_quit)
        notebook = self.builder.get_object('notebook1')
        notebook.connect("switch-page", self.on_notebook1_switch_page)
        self.on_notebook1_switch_page(notebook, None,
                                      notebook.get_current_page())

    def on_notebook1_switch_page(self, widget, label, page):
        for p in range(widget.get_n_pages()):
            container = widget.get_nth_page(p)
            if not p == page:
                for c in container.get_children():
                    try:
                        c.hide_all()
                    except AttributeError:
                        c.hide()
            else:
                for c in container.get_children():
                    try:
                        c.show_all()
                    except AttributeError:
                        c.show()


if __name__ == '__main__':
    notebookwindow = NotebookWindow()
    Gtk.main()

In my original answer I recorded and re-instated the requested sizes. This does not work in general, because the requested size is only a minimal size. I would have to record a maximum size, in order for this to work, though.