2010-08-23 18 views
6

Tengo problemas de rendimiento al insertar muchas filas en una vista de árbol GTK (usando PyGTK) o al modificar muchas filas. El problema es que el modelo parece ser recurrido después de cada cambio (inserción/modificación). Esto hace que la GUI se cuelgue por varios segundos. Dejar el modelo sin ordenar al comentar model.set_sort_column_id(SOME_ROW_INDEX, gtk.SORT_ASCENDING) elimina estos problemas.GtkTreeView penalización de rendimiento de inserción/actualización debido a la clasificación

Por lo tanto, me gustaría desactivar la clasificación mientras estoy insertando o modificando el modelo, y volver a habilitarlo después. Desafortunadamente, la clasificación no se puede desactivar con model.set_sort_column_id(-1, gtk.SORT_ASCENDING). Usando las funciones de congelación/descongelación no funciona bien:

treeview.freeze_child_notify() 

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

Entonces, ¿cómo puedo desactivar la clasificación? ¿O hay un método mejor para inserciones/modificaciones a granel?


solución

Gracias a la información y enlaces bobince proporcionado en su respuesta, he comprobado algunas de las alternativas:

1) Maniquí de clasificación

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() 

Esto redujo el tiempo de aproximadamente 11 segundos a 2 segundos. ¡Guauu! Pero podría ser mejor, esto fue solo para 1000 filas.

2) Extracción de modelo al actualizar

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

No se diferencia notable, 11 segundos.

3) Maniquí clasificación y el fresco truco generador de la 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) 

El resultado: Los mismos estimado de 2 segundos como en solución 1), pero la GUI reacciona durante este tiempo. Yo prefiero este método El módulo 200 se puede modificar para hacer que la GUI sea más o menos reactiva si es necesario.

Tal vez es incluso posible la subclase gtk.TreeStore para obtener mejores resultados? Todavía no lo he intentado, pero la opción 3) es lo suficientemente buena por ahora.

Respuesta

2

Parece que estás cerca. Consulte el FAQ para obtener más notas. En particular, también debe configurar default_sort_order (ahora puede usar None, así como la versión ficticia lambda en ese ejemplo, para un mejor rendimiento) para asegurarse de que no haya clasificación, y eliminar el modelo de la vista de árbol durante la duración de las operaciones .

Si se trata de una gran cantidad de cambios, será mejor que cree y configure un modelo completamente nuevo.

+0

Gracias, fue realmente útil :) Consulte mi pregunta para conocer algunas soluciones que he probado en función de la información que ha proporcionado. – AndiDog

Cuestiones relacionadas