Search code examples
pythonpython-3.xgtkpygobjectgtktreeview

Spinner in a PyGObject Gtk.TreeView does not spin


It is not clear for me how to use Gtk.SpinnerCellRenderer in a Gtk.TreeView with a Gtk.ListStore as model.

In this example the spinner is shown but it is inactive. It doesn't spin.

#!/usr/bin/env python3
import random
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class TreeView(Gtk.TreeView):
    def __init__(self):
        # model
        self.model = Gtk.ListStore.new([bool, int])
        for i in range(5):
            self.model.append([random.choice([True, True, False]), i])

        # view
        Gtk.TreeView.__init__(self, self.model)

        # column bool (as spinner)
        self.spinner_renderer = Gtk.CellRendererSpinner.new()
        col_bool = Gtk.TreeViewColumn('bool',
                                      self.spinner_renderer,
                                      active=0)
        self.append_column(col_bool)

        # column int
        col_int = Gtk.TreeViewColumn('int',
                                     Gtk.CellRendererText(),
                                     text=1)
        self.append_column(col_int)


class Window(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title='Mein Gtk-Fenster')
        self.set_default_size(100, 120)

        self.view = TreeView()
        self.add(self.view)

        self.connect('destroy', Gtk.main_quit)
        self.show_all()

if __name__ == '__main__':
    win = Window()
    Gtk.main()

Solution

  • #!/usr/bin/env python3
    import random
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk
    from gi.repository import GObject
    
    class TreeView(Gtk.TreeView):
        def __init__(self):
            # model
            self.model = Gtk.ListStore.new([bool, int])
            for i in range(5):
                self.model.append([random.choice([True, True, False]), i])
    
            # view
            Gtk.TreeView.__init__(self, self.model)
    
            # column bool (as spinner)
            self.spinner_renderer = Gtk.CellRendererSpinner()
            col_bool = Gtk.TreeViewColumn('bool', self.spinner_renderer, active=0)
            self.append_column(col_bool)
    
            # column int
            col_int = Gtk.TreeViewColumn('int', Gtk.CellRendererText(), text=1)
            self.append_column(col_int)
    
        def on_spinner_pulse(self):
            for row in self.model:
                if row[0]:
                    if row[1] == 150:
                        row[1] = 0
                    else:
                        row[1] += 1
            self.spinner_renderer.set_property("pulse", row[1])
            return True
    
    class Window(Gtk.Window):
        def __init__(self):
            Gtk.Window.__init__(self, title='CellRendererSpinner')
            self.set_default_size(200, 400)
    
            self.view = TreeView()
            self.add(self.view)
    
            self.connect('destroy', Gtk.main_quit)
            self.show_all()
    
    if __name__ == '__main__':
        win = Window()
        GObject.timeout_add(100, win.view.on_spinner_pulse)
    Gtk.main()
    

    increment the Gtk.CellRendererSpinner :pulse property at regular intervals

    1. Increase "pulse" value of cellrendererspinner by calling self.spinner_renderer.set_property("pulse", newValue) in a method

    2. Call that method repeatedly with GObject.timeout_add(milliseconds, method) function