У меня проблемы с производительностью при вставке многих строк в древовидную структуру 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),но графический интерфейс реагирует в течение этого времени.Я предпочитаю этот метод.Modulo 200 может быть настроен, чтобы сделать графический интерфейс более или менее реактивным, если это необходимо.
Может быть, даже возможно создать подкласс gtk.TreeStore
, чтобы получить лучшие результаты?Еще не пробовал, но вариант 3) пока достаточно.