Gtkmm - force redraw
-
Hallo zusammen.
Ich habe ein Gtkmm Applikation unter Windows, in der ein Diagramm dargestellt ist, dass Messdaten anzeigt. Das Diagramm ist von Gtk::DrawingArea abgeleitet.
Das es sich um Messdaten handelt, die teilweise im 10ms Takt erneuert werden, möchte ich natürlich auch die Anzeige entsprechend oft neuzeichnen. Nur leider finde ich im Netz sehr widersprüchliche Angaben, welchen Weg man dazu benutzt. Zwei Sachen habe ich ausprobiert:getLiveData() liest die Messdaten aus einer DLL, aufgerufen wird der abgebildete Code von einem (WinAPI-)Thread.
if(getLiveData() == 0) { // force our program to redraw Glib::RefPtr<Gdk::Window> win = get_window(); if (win) { Gdk::Rectangle r(0, 0, get_allocation().get_width(), get_allocation().get_height()); win->invalidate_rect(r, false); } }
Hierbei passiert leider gar kein Update. Nur wenn ich das Fenster ändere (größer, kleiner, ...) funktioniert das Update, denn on_expose_event() wird aufgerufen.
Andere Variante, dia ist mein Diagramm-Objekt, von Gtk::DrawingArea abgeleitet:
if(getLiveData() == 0) { dia.queue_draw(); }
Hierbei läuft die Sache ne Weile gut (~30 Sekunden, etwa 1000 - 3000 Messungen), es wird brav geupdatet. Nach dieser Zeit gerät das Update-Interval ins Stocken, bis es ganz aufhört. Die App ist aber nicht abgestürzt. Wenn ich dann was am Fenster ändere funktioniert es wieder ne Weile wie gewollt. Speicherleck ist auch keins drin. Das habe ich bereits ausgeschlossen.
So, viel Text. Wie macht man es richtig?
Danke
-
Dass die erste Variante nicht funktioniert liegt daran, dass bei
win->invalidate_rect(r, false);
' das
falseeinem
true` weichen sollte.Das
queue_draw()
in der zweiten Variante sollte eigentlich innerhalb des dia-Widgets ausgeführt werden, wenn du schon ein eigenes Widget dafür abgeleitet hast.Was der Fehler ist, kann ich mir nicht erklären; selbst der Gnome System Monitor updatet seinen schicken Graphen mit
queue_draw()
.
-
Okay, danke erstmal für die Antwort.
Welche der beiden Methoden ist denn vorzuziehen? Wo liegt der Unterschied?
-
Hab jetzt die beiden Möglichkeiten in die dia-Klasse gepackt. Das gleiche Verhalten. Ein einfaches cout in der on_expose_event()-Methode zeigt mir, dass sie nach einer Weile nicht mehr aufgerufen wird. Wenn ich dann was am Fenster ändere und der on_expose_event() vom System kommt, gehts wieder eine Weile. Aber nicht lange.
/edit
Könnte es vielleicht daran liegen, dass ich keinen Gtk-Thread verwende? Mein Thread ruft die Methoden auf.
-
Eigentlich existiert kein Unterschied, die queue_draw()-Methode finde ich etwas schicker.
Zu deinem Thread-Problem: Es muss kein GTK-Thread sein, solange du artig die Spielregeln befolgst:
<a href= schrieb:
Gtkmm FAQ">Neither X, nor GDK nor GTK+ nor gtkmm are thread safe by themselves. You must use either the gdk_threads_{enter,leave}() functions to protect any and every call to GDK/GTK+/gtkmm functions, or alternatively, ensure that only a single thread makes such calls.
Dass ein Widget sich selbst in einem eigenen Thread zeichnet finde ich fragwürdig, probiere mal, ob es wirklich Vorteile bringt, einen zusätzlichen Thread dafür zu verwenden. Es wird wirklich viel leicher mit nur einem GUI-Thread (die Daten kannst du in einem anderen auslesen, das macht nichts; du musst nur noch die Daten mit einem Dispatcher übergeben).
Wenn du dich noch nicht mit Multithreading in Gtkmm auseinandergesetzt hast, würde ich dir mal empfehlen, einmal die Beispielprogramme anzuschauen: http://library.gnome.org/devel/glibmm/unstable/examples.html
-
queue_post schrieb:
Dass ein Widget sich selbst in einem eigenen Thread zeichnet finde ich fragwürdig, probiere mal, ob es wirklich Vorteile bringt, einen zusätzlichen Thread dafür zu verwenden.
Da haben wir uns falsch verstanden. Ich habe einen Thread der die Daten holt und in ein gemeinsamen Puffer legt. Dieser Puffer ist mit CriticalSections geschützt. Es verklemmt sich ja auch nichts.
Wenn meine Datenerfassung abgeschlossen ist, will ich mit dem Thread nur ein Signal setzen, dass das Fenster jetzt vom GTK-System neugezeichnet werden soll. Ich will nicht selbst im Thread zeichnen.