在将多行插入GTK树视图(使用PyGTK)时,或者在修改多行时,我遇到了性能问题。问题是模型似乎在每次更改(插入/修改)后都会使用。这会导致GUI挂起多秒钟。通过注释掉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()
那么,我怎样才能禁用排序?或者有更好的批量插入/修改方法吗?
解决方案
感谢他在答案中提供的信息和链接,我检查了一些替代方案:
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)
结果:与解决方案1)相同的估计2秒,但GUI在此期间作出反应。我更喜欢这种方法。如果需要,可以调整模200以使GUI具有或多或少的反应性。
也许甚至可以将gtk.TreeStore
子类化以获得更好的结果?还没有尝试过,但是选项3)现在还不错。
答案 0 :(得分:2)
听起来你几乎就在那里。有关详细说明,请参阅FAQ。特别是,您还应该设置default_sort_order
(您现在可以使用None
以及该示例中的虚拟比较lambda以获得更好的性能)以确保没有排序,并从中删除模型操作期间的树视图。
如果进行了大量更改,您最好创建并设置一个完整的新模型。