treeview & liststore: flackert beim Neuaufbau

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
w.olle
User
Beiträge: 27
Registriert: Sonntag 15. November 2009, 00:28

Hallo,
ich habe ein Programm, welches Daten aus einer SQL DB abfragt und in einer Tabelle darstellt. Da sich die Daten schnell ändern frage ich die DB alle 5 Sekunden ab, und erzeuge daraus ein liststore. Da ich zuerst ein liststore.clear machen muss, flackert die Tabelle jedes mal wenn sie neu aufgebaut wird.

Hat jemand vielleicht eine Idee, wie ich das besser/anders machen kann ?

Danke,
Wolle
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Anstatt das Model immer zu löschen (model.clear()) kannst du die jeweiligen TreeIter auch einfach updaten. Ich habe dazu immer ein Dict mit Referenzen auf die jeweiligen TreeIter angelegt, so dass man einfacher daran gelangt: http://paste.pocoo.org/show/270119/

Achtung, in dem Code sind ein paar Don'ts, mir spring gerade besonders dieser try-except-Block ins Auge. Ich hoffe, die grundlegende Idee wird daraus verständlich.

Damit konnte ich das Flackern bei mir abstellen (wenn ich mich recht erinnere).

Gruß,

brb
w.olle
User
Beiträge: 27
Registriert: Sonntag 15. November 2009, 00:28

Vielen Dank.
Soweit ich das verstehe verwendest du die Funktion model.set() um es zu aktualisieren ? Was bewirkt eigentlich der * vor dem 'ret' ?

Gruß,
Wolle
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hi w.olle!

Hier findest du ein paar Informationen dazu - was Besseres habe ich auf die Schnelle nicht gefunden. Dort schau mal nach dem Stichwort "Entpacken einer Parameterliste".

Gruß,

brb
w.olle
User
Beiträge: 27
Registriert: Sonntag 15. November 2009, 00:28

Ach ja,
wenn ich ehrlich bin, kenne ich die Seite sogar (damit war ich damals angefangen mir Python rein-zuziehen :lol: ).

Nochmals besten Dank, ich glaube jetzt komme ich damit klar.

Danke !
Wolle
w.olle
User
Beiträge: 27
Registriert: Sonntag 15. November 2009, 00:28

Hallo,
vielleicht kannst du mir nochmal helfen mit dem treeview:

Ich habe einige nicht erklärbare Fehlermeldungen:
Warning (from warnings module):
File "/home/wolfgang/Desktop/parcour/gui/main.py", line 943
gtk.main()
Warning: g_object_ref: assertion `object->ref_count > 0' failed
oder
Warning (from warnings module):
File "/home/wolfgang/Desktop/parcour/gui/main.py", line 945
gtk.main()
Warning: g_object_ref: assertion `G_IS_OBJECT (object)' failed
Im Moment starte ich das Aktualisieren des TreeViews von einem weiteren thread, indem ich per __gsignals__ die entsprechende Funktion in meinem Hauptthread starte. Ich starte sie alle 2 sekunden, aber ich habe auch schon mal alle 5 Sekunden versucht (ohne Erfolg).
Ich habe deinen Code fast 1 zu 1 übernommen. Ich habe lediglich noch ein paar Zeilen zugefügt, in denen ich überflüssige Einträge aus dem TreeView lösche.

Manchmal stürzt das Programm auch einfach ab, nachdem der TreeView geleert wurde.

So langsam werde ich Ratlos, da sich nicht genau nachvollziehen lässt, woher das kommt.
Hier der code.
Gruß, Wolle
Zuletzt geändert von w.olle am Sonntag 14. November 2010, 14:17, insgesamt 1-mal geändert.
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

w.olle hat geschrieben:Manchmal stürzt das Programm auch einfach ab, nachdem der TreeView geleert wurde.
Mit welcher Fehlermeldung / welchem Verhalten?

so Konstrukte wie diese solltest du vermeiden:

Code: Alles auswählen

except:
Fange nur diese Ausnahmen die du auch erwartest.
w.olle
User
Beiträge: 27
Registriert: Sonntag 15. November 2009, 00:28

Hallo,
es ist immer das Gleiche: Nachdem die ersten paar Zeilen zum TreeView (gtk.ListStore) hinzugefügt wurden kommt immer folgende Meldung:

Code: Alles auswählen

Warning (from warnings module):
  File "/home/wolfgang/Desktop/parcour/gui/test.py", line 943
    gtk.main()
Warning: g_object_ref: assertion `object->ref_count > 0' failed


Warning (from warnings module):
  File "/home/wolfgang/Desktop/parcour/gui/test.py", line 943
    gtk.main()
Warning: g_object_ref: assertion `G_IS_OBJECT (object)' failed

Warning (from warnings module):
  File "/home/wolfgang/Desktop/parcour/gui/test.py", line 943
    gtk.main()
Warning: g_object_unref: assertion `G_IS_OBJECT (object)' failed
Es stürtzt nicht jedesmal ab, aber wenn, dann immer, wenn der TreeView geleert wird (sieht man am print 'del'). Gerade kam beim Absturz z.B. die folgende Meldung:

Code: Alles auswählen

del
del
del
del
Warning (from warnings module):
  File "/home/wolfgang/Desktop/parcour/gui/test.py", line 943
    gtk.main()
GtkWarning: gtk_list_store_get_value: assertion `VALID_ITER (iter, list_store)' failed


Warning (from warnings module):
  File "/home/wolfgang/Desktop/parcour/gui/test.py", line 943
    gtk.main()
Warning: g_object_set_property: assertion `G_IS_VALUE (value)' failed
del
Warning (from warnings module):
  File "/home/wolfgang/Desktop/parcour/gui/test.py", line 943
    gtk.main()
Warning: g_value_unset: assertion `G_IS_VALUE (value)' failed
...und beim zweiten Druchlauf stürtzte es mit dieser Meldung ab:

Code: Alles auswählen

Warning (from warnings module):
  File "/home/wolfgang/Desktop/parcour/gui/test.py", line 943
    gtk.main()
GtkWarning: /build/buildd/gtk+2.0-2.22.0/gtk/gtktreeview.c:5025 (gtk_tree_view_bin_expose): assertion `has_next' failed.
There is a disparity between the internal view of the GtkTreeView,
and the GtkTreeModel.  This generally means that the model has changed
without letting the view know.  Any display from now on is likely to
be incorrect.
Ich habe inzwischen try - except weggenommen, aber daher kann es eigentlich nicht kommen. Ich bin ziemlich ratlos. Leider kann ich TreeView.clear() nicht nehmen, da auch öfters nur einzelne Zeilen gelöscht werden.

Gruß, Wolle
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Ich finde den Codeabschnitt ab 92 irgendwie etwas merkwürdig:

Ich könnte mir gut vorstellen, dass das Problem damit zusammenhängt, dass du über die TreeIter des TreeStores iterierst, gleichzeitig aber auch Iters entfernst - ich denke, dass das zu Fehlern führt. Hier könnten unter Umständen TreeRowReferences sinnvoll sein.

Zur Not würde ich erstmal die zu löschenden Iter in eine Liste packen und *nach* dem Iterieren löschen.

Die Fehlermeldung "gtk_list_store_get_value: assertion `VALID_ITER (iter, list_store)' " zeigt ja, dass du irgendwie mit ungültigen TreeIter operierst. Wahrscheinlich hängt das echt damit zusammen, dass du das Objekt, über das du iterierst, beim iterieren veränderst.

Deine Thread-Klasse ist doch eigentlich nur ein selbstgebauter Ersatz für gobject.timeout_add(), oder? Dann würde ich das auch verwenden:

Code: Alles auswählen

gobject.timeout_add(1000, self.fill_store)
Wichtig ist dann aber, dass self.fill_store() "True" zurück gibt, damit es nächstes Mal wieder aufgerufen wird.
w.olle
User
Beiträge: 27
Registriert: Sonntag 15. November 2009, 00:28

Hey, super !!
ich habe zum einen gobject.timeout_add() eingefügt (super, kannte ich gar nicht), und ich verwende jetzt eine liste in der ich die zu löschenden iter sammle. Klappt bislang ohne Probleme.

Zur Vollständigkeit:
Ich habe noch vor jedem gtk.ListStore.set(), bzw. gtk.ListStore.remove() ein gtk.gdk.threads_enter() und dahinter ein gtk.gdk.threads_leave() eingefügt, damit die GUI besser läuft.
Hier der endgültige code

Danke, Dank, Danke für die schnelle Hilfe !! :D
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo Wolle,

freut mich, dass es läuft - allerdings benötigst du threads_enter() bzw. threads_leave() nur, wenn du tatsächlich aus einem anderen Thread ein GTK-Objekt manipulierst. Und das machst du ja nicht mehr, weil gobject.timeout_add() meines Wissens auf den GTK-Thread aufspringt (ähnlich wie idle_add()).

Kurz gesagt: Eigentlich (TM) sollte das mit threads_enter() / threads_leave() keinen Unterschied bewirken :).

Besten Gruß,

brb
w.olle
User
Beiträge: 27
Registriert: Sonntag 15. November 2009, 00:28

Stimmt,
hast recht. Ich habs jetzt weggelassen.

Nochmals DANKE :!:
Wolle
Antworten