FAQ Index - Search - Recent Changes - Everything - Add entry

<< Previous Entry | FAQ Entry 13.43 | Next Entry >>

13.43. Are there tips for improving performance when adding many rows to a Treeview?

You should freeze TreeView updates and detach the model before adding a lot of rows:

 treeview.freeze_child_notify()
 treeview.set_model(None)

 # Add rows to the model
 # ...

 treeview.set_model(model)
 treeview.thaw_child_notify()
Note that sorting can slow down addition dramatically, and if you use a sort function, you should set an alternative one for the duration of the insertion:

  model.set_default_sort_func(lambda *args: -1) 
  model.set_sort_column_id(-1, gtk.SORT_ASCENDING)
Alternatively, you can just start with a new model, prefill it before attaching it to the view, and enable sorting at the end of this process.

Another way to make adding rows to treeview "feels faster" is to progressively add rows using a generator function:

  def fill_tree(tree, items, step=128):
      '''Generator to fill the listmodel of a treeview progressively.'''
      n = 0
      model = tree.get_model() # a listmodel in this example

      tree.freeze_child_notify()
      for it in items:
	  model.append(it) # Fill the model

	  # yield to gtk main loop once awhile
	  n += 1
	  if (n % step) == 0:
	      tree.thaw_child_notify()
	      yield True
	      tree.freeze_child_notify()

      tree.thaw_child_notify()
      # stop idle_add()
      yield False

  def on_load_tree(w, tree):
      '''Event handler'''
      keys = [(x,) for x in range(100000)]

      # fill the tree during idle cycles.
      loader = fill_tree(tree, keys)
      gobject.idle_add(loader.next)
For a very large number of rows, you might want to have a look at Easygrid [www.earthenware-services.org] by John Gill:

"I've found the liststore ok up to about 10-20K rows, after that I start to run into problems. With easygrid I'm able to browse tables with 500K rows with no performance problems."

Finally, the Ruby/Gtk TreeView tutorial states that

"You should not keep around a lot of tree row references if you have so many rows, because with each insertion (or removal) every single tree row reference will check whether its path needs to be updated or not."

For ListStore and TreeStore, you may be able to use iters instead of TreeRowReferences, as, according to the pygtk manual "...some models guarantee that an treeiter is valid for as long as the node it refers to is valid (most notably the gtk.TreeStore and gtk.ListStore)."

PyGTK FAQ Wizard | PyGTK Homepage | Feedback to faq at pygtk.org