ich habe ein Problem mit der Aktualisierung des Fensterinhalts in einem GTK-Programm. Das Programm soll in regelmäßigen Abständen ein jpeg-Bild von einem Server laden, mit diversen Filtern verarbeiten und in einem Fenster darstellen.
Herunterladen und verarbeiten funktioniert. Nur das (ich dachte einfache) Aktualisieren der Darstellung klappt nicht.
Der Bildinhalt wird nicht aktualisiert. Im Anhang mein Testprogramm.
Dies liest zur Vereinfachung im Wechsel 2 unterschiedliche Jpeg-Bilder identischer Größe mit gdk_pixbuf_new_from_file() ein.
Inzwischen habe ich festgestellt, dass die Verarbeitungszeit meiner download() Routine eine Rolle spielt. Diese wird über g_timeout_add() alle 0,2 Sekunden aufgerufen.
Wenn die Dauer der download() Routine länger zur Verarbeitung benötigt, klappt es nicht mehr (Simuliert durch usleep(250000)).
Laut Doku von g_timeout_add() wird nicht versucht, verpasste Zeitpunkte aufzuholen sondern einfach das nächste passende Intervall verwendet.
Wäre schön, wenn jemand einen Tipp hat ...
P.S.:
Gibt es nicht noch eine bessere Methode ein GdkPixbuf Objekt zu Aktualisieren ohne jedes mal alle Puffer zu löschen, neu aufzubauen? (Siehe Teil unter "UPDATE IMAGE" Meldung) Die von mir verwendet Methode finde ich sehr umständlich und nicht sehr effizient. Sowas wie get_image_update() wäre schön...
Ab hier mein Testprogramm (in C) :
Code: Alles auswählen
// gcc ReloadTest.c `pkg-config gtk+-3.0 --cflags` `pkg-config gtk+-3.0 --libs` -ljpeg -o ReloadTest
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
struct geo_data {
GdkPixbuf *pixbuf;
GtkWidget *image;
GtkWidget *window;
};
void on_destroy (GtkWidget *widget G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED)
{
gtk_main_quit ();
}
int download(struct geo_data *geo)
{
static int flag=0;
flag=!flag;
// Platzhalter für Download-Routine
// BUG : If delay > timeout, window content isn't updated and image area stays transparent!
usleep(250000);
// Bilddarstellung aktualisieren
if(geo->pixbuf==NULL) {
puts("*** NEUER PIXBUF ***");
geo->pixbuf=gdk_pixbuf_new_from_file("DUMMY.jpg",NULL);
}
if(geo->image==NULL) {
puts("*** NEUES IMAGE ***");
geo->image=gtk_image_new_from_pixbuf(geo->pixbuf);
gtk_container_add(GTK_CONTAINER (geo->window), geo->image);
gtk_widget_show_all(geo->window);
} else {
printf("*** UPDATE IMAGE %d ***\n",flag);
gtk_widget_destroy(geo->image);
geo->pixbuf=gdk_pixbuf_new_from_file(flag?"dummy.jpg":"DUMMY.jpg",NULL);
geo->image=gtk_image_new_from_pixbuf(geo->pixbuf);
gtk_container_add(GTK_CONTAINER (geo->window), geo->image);
gtk_widget_show_all(geo->window);
// gtk_widget_show(geo->image);
// gtk_widget_queue_draw(geo->image);
}
return 1;
}
int main(int argc, char *argv[])
{
struct geo_data geo;
memset(&geo,0,sizeof(struct geo_data));
gtk_init (&argc, &argv);
geo.window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect (geo.window, "destroy", G_CALLBACK(on_destroy), NULL);
g_signal_connect (geo.window, "close", G_CALLBACK(on_destroy), NULL);
//geo.pixbuf=gdk_pixbuf_new_from_file("dummy.jpg",NULL);
//geo.image=gtk_image_new_from_pixbuf(geo.pixbuf);
//gtk_container_add(GTK_CONTAINER (geo.window), geo.image);
// Einmal manuell aufrufen vor gtk_main();
download(&geo);
g_timeout_add(200,(GSourceFunc)download,(gpointer)&geo);
//gtk_widget_show_all(geo.window);
puts("*** GTK_MAIN START ***");
gtk_main();
return 0;
}
https://geo-laser.de/support/dummy.jpg
https://geo-laser.de/support/DUMMY.jpg