GtkTreeView вставка / обновление снижение производительности из-за сортировки

У меня проблемы с производительностью при вставке многих строк в представление дерева GTK (используя PyGTK) - или при изменении многих строк. Проблема в том, что модель, кажется, восстанавливается после каждого изменения (вставка / модификация). Это приводит к зависанию графического интерфейса на несколько секунд. Оставив модель не отсортированной, закомментировав model.set_sort_column_id (SOME_ROW_INDEX, gtk.SORT_ASCENDING) устраняет эти проблемы.

Поэтому я хотел бы отключить сортировку при вставке или изменении модели, и включите его позже. К сожалению, сортировку нельзя отключить с помощью model.set_sort_column_id (-1, gtk.SORT_ASCENDING) . Использование функций замораживания / оттаивания также не работает:

treeview.freeze_child_notify()

try:
    for row in model:
        # ... change something in row ...
finally:
    treeview.thaw_child_notify()

Итак, как я могу отключить сортировку? Или есть лучший способ для массовых вставок / модификаций?


Решение

Благодаря информации и ссылкам, предоставленным bobince в его ответе, я проверил некоторые из альтернатив:

1) Макетная сортировка

 tv.freeze_child_notify()
 sortSettings = model.get_sort_column_id()
 model.set_default_sort_func(lambda *unused: 0) # <-- can also use None but that is slower!
 # model.set_default_sort_func(lambda *unused: 1) <-- slow
 # model.set_default_sort_func(lambda *unused: -1) <-- crash (access violation in gtk_tree_store_move_after?!)
 model.set_sort_column_id(-1, gtk.SORT_ASCENDING)
 # change rows
 model.set_sort_column_id(*sortSettings)
 tv.thaw_child_notify()

Это сократило время с 11 до 2 секунд. Вот Это Да! Но могло бы быть и лучше, это было только для 1000 строк.

2) Удаление модели при обновлении

tv.set_model(None)
# change rows
tv.set_model(model)

Нет заметной разницы, 11 секунд.

3) Макетная сортировка и крутой трюк генератора из PyGTK FAQ

 def gen():
      tv.freeze_child_notify()
      sortSettings = model.get_sort_column_id()
      model.set_default_sort_func(lambda *unused: 0)
      model.set_sort_column_id(-1, gtk.SORT_ASCENDING)

      i = 0
      for row in rowsToChange:
           i += 1
           # change something
           if i % 200 == 0:
                # freeze/thaw not really  necessary here as sorting is wrong because of the
                # default sort function
                yield True

      model.set_sort_column_id(*sortSettings)
      tv.thaw_child_notify()
      yield False

 g = gen()
 if g.next(): # run once now, remaining iterations when idle
     gobject.idle_add(g.next)

Результат: те же примерно 2 секунды, что и в решении 1), но GUI реагирует в течение этого времени. Я предпочитаю этот метод. Модуль 200 может быть изменен, чтобы сделать графический интерфейс более или менее реактивным, если это необходимо.

Может быть, возможно даже создать подкласс gtk.TreeStore для получения лучших результатов? Еще не пробовал, но вариант 3) пока достаточно.

6
задан gpoo 23 January 2013 в 06:46
поделиться