Search code examples
pythonpygtk

pygtk how to replace the contents of a tab on switch-page


Suppose i have something like this for a basic notebook:

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk


class MainWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="My App")
        self._init = False # Try to stop recursion errors during setup

        self.notebook = Gtk.Notebook()

        self.page0 = Gtk.Label(label='Some text')
        self.page1 = Gtk.Label(label='More text')

        self.notebook.append_page(self.page0, Gtk.Label(label='p1'))
        self.notebook.append_page(self.page1, Gtk.Label(label='p2'))

        self.notebook.connect('switch-page', self.refresh)

        self.add(self.notebook)
        self._init = True


    def refresh(self, notebook, page, page_num):
        if page_num == 0 and self._init:
            self.remove(self.page0)
            self.page0 = Gtk.Label(label='Some more and different text')
            self.notebook.prepend_page(self.page0, Gtk.Label(label='p1'))
            self.notebook.set_current_page(0)

win = MainWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

What I'm trying to do is when the user clicks on the first tab (hence the switch-page signal) that the tab gets "refreshed" (in this case just replacing the text but it could be more substantial change, like changing the Widget being shown). Should I being trying to delete the "old" tab and insert a new one at position 0, or call some function on the tab to update what it shows?

The code as shown crashes with recursion issues (I guess switch-page gets called during setup?), which is why I thought maybe calling some sort of updateWidegt() function would be better than trying to delete a page. But I'm not sure with that how to get the notebook to "see" the changes.


Solution

  • The reason for the infinite recursion is that the switch-page handler refresh(), emits the signal when you are updating the pages. You can avoid that by not changing the pages, but only updating the widgets within the pages, as you mention. I updated your example below:

    from gi.repository import Gtk
    
    class MainWindow(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self, title="My App")
            self.notebook = Gtk.Notebook()
            self.count = 0
    
            self.page0 = Gtk.Label(label='Some text')
            self.page1 = Gtk.Label(label='More text')
    
            self.notebook.append_page(self.page0, Gtk.Label(label='p1'))
            self.notebook.append_page(self.page1, Gtk.Label(label='p2'))
    
            self.notebook.connect('switch-page', self.refresh)
    
            self.add(self.notebook)
    
        def refresh(self, notebook, page, page_num):
            self.count += 1
            if page_num == 0:
                self.page0.set_label('Some more and different text {count}'.format(count=self.count))
    
    
    win = MainWindow()
    win.connect("destroy", Gtk.main_quit)
    win.show_all()
    Gtk.main()
    

    If you want to add widgets, let your notebook page be a Gtk.Box or another container widget, and add widgets to it. Another way that can be simpler than adding/removing widgets dynamically, is to add all widgets at startup, and simply hide/show them when appropriate.