2010-08-23 9 views
6

Ich habe Leistungsprobleme beim Einfügen vieler Zeilen in eine GTK-Strukturansicht (mit PyGTK) - oder beim Ändern vieler Zeilen. Das Problem ist, dass das Modell nach jeder Änderung neu sortiert wird (Einfügen/Ändern). Dies führt dazu, dass die GUI für mehrere Sekunden hängen bleibt. Wenn Sie das Modell unsortiert lassen, indem Sie den Befehl model.set_sort_column_id(SOME_ROW_INDEX, gtk.SORT_ASCENDING) auskommentieren, werden diese Probleme behoben.GtkTreeView einfügen/update Leistungseinbuße wegen der Sortierung

Daher möchte ich die Sortierung deaktivieren, während ich das Modell einfügen oder ändern, und es anschließend wieder aktivieren. Leider kann die Sortierung nicht mit model.set_sort_column_id(-1, gtk.SORT_ASCENDING) deaktiviert werden. ist die Frost/Tau-Funktionen nicht funktionieren entweder:

treeview.freeze_child_notify() 

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

Also, wie kann ich die Sortierung deaktivieren? Oder gibt es eine bessere Methode für Bulk-Einsätze/Modifikationen?


Lösung

Dank der Informationen und Links in seiner Antwort zur Verfügung gestellt bobince, überprüfte ich einige der Alternativen aus:

1) Dummy Sortierung

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

Dies brachte die Zeit von ungefähr 11 Sekunden auf 2 Sekunden herunter. Beeindruckend! Aber könnte besser sein, das war nur für 1000 Reihen.

2) Modell entfernt wird, während

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

No noticable Differenz aktualisiert wird, 11 Sekunden.

3) Dummy Sortieren und der kühle Generator Trick vom 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) 

Das Ergebnis: Die gleichen schätzungsweise 2 Sekunden, wie in Lösung 1), aber die GUI während dieser Zeit reagiert. Ich bevorzuge diese Methode. Der Modulo 200 kann optimiert werden, um die GUI bei Bedarf mehr oder weniger reaktiv zu machen.

Vielleicht ist es sogar möglich, gtk.TreeStore von der Unterklasse zu entfernen, um bessere Ergebnisse zu erhalten? Ich habe das noch nicht ausprobiert, aber Option 3) ist jetzt gut genug.

Antwort

2

Klingt, als wären Sie fast da. Weitere Informationen finden Sie unter FAQ. Insbesondere sollten Sie auch die default_sort_order (Sie können jetzt None sowie das Dummy vergleichen Lambda in diesem Beispiel für eine bessere Leistung), um sicherzustellen, dass keine Sortierung, und entfernen Sie das Modell aus der Baumansicht für die Dauer der Operationen .

Wenn es viele Änderungen gibt, können Sie besser ein neues Modell erstellen und einstellen.

+0

Danke, das war wirklich hilfreich :) Siehe meine Frage für einige Lösungen, die ich anhand der von Ihnen bereitgestellten Informationen getestet habe. – AndiDog

Verwandte Themen