2012-05-31 5 views
4

У меня есть приложение GTK+, написанное в C, которое загружает матрицу анимированных файлов GIF. Эти GtkImages автоматически запускают анимацию, когда они загружаются, а затем останавливаются, когда анимация завершена. Как бы перезапустить анимацию каждого GtkImage, содержащего GIF, и являются ли сигналы, сгенерированные при завершении анимации?Как запустить и остановить GIF-анимацию GtkImage в GTK +

спасибо.

EDIT:
ли использование gdk_pixbuf_animation_get_iter() описано here сделать это возможным?

Полный код приведен ниже.

/* 
* Compile me with: 
* gcc -o reels reels.c $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0) 
*/ 

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <time.h> 

/* GTK */ 
#include <gdk/gdkx.h> 
#include <gtk/gtk.h> 

/**** prototypes ****/ 

static void destroy (GtkWidget*, gpointer); 
GdkPixbuf *create_pixbuf(const gchar * filename); 
GtkWidget *SetupWindow(gchar *data, const gchar *filename); 
static void destroy (GtkWidget *window, gpointer data); 
void btnSpin_clicked(GtkWidget *button, gpointer data); 
void btnExit_clicked(GtkWidget *button, gpointer data); 

/********************/ 

GtkWidget *images[3][5]; 

static void destroy (GtkWidget *window, gpointer data) 
{ 
    gtk_main_quit(); 
} 

void btnSpin_clicked(GtkWidget *button, gpointer data) 
{ 
    printf("Spin Button pressed.\n"); 

    return; 
} 

void btnExit_clicked(GtkWidget *button, gpointer data) 
{ 
    gtk_main_quit(); 

    return; 
} 


GtkWidget *SetupWindow(gchar *data, const gchar *filename) 
{ 
    GdkPixmap *background; 
    GdkPixbuf *pixbuf; 
    GdkScreen *ourscreen; 
    GdkColormap *colormap; 
    GtkStyle *style; 
    GdkColor fg; 
    GdkColor bg; 
    GError *error = NULL; 
    GdkRectangle *rect; 
    GtkWidget *window; 

    pixbuf = gdk_pixbuf_new_from_file (filename,&error); 
    if (error != NULL) { 
     if (error->domain == GDK_PIXBUF_ERROR) { 
      g_print ("Pixbuf Related Error:\n"); 
     } 
     if (error->domain == G_FILE_ERROR) { 
      g_print ("File Error: Check file permissions and state:\n"); 
     } 

     g_printerr ("%s\n", error[0].message); 
    } 

    gdk_pixbuf_render_pixmap_and_mask (pixbuf, &background, NULL, 0); 
    style = gtk_style_new(); 
    style->bg_pixmap[0] = background; 
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_title (GTK_WINDOW (window), data); 
    // gtk_window_maximize(GTK_WINDOW(window)); 
    gtk_window_set_modal (GTK_WINDOW (window),TRUE); 
    gtk_window_set_default_size(GTK_WINDOW(window),628,530); 
    gtk_widget_set_style (GTK_WIDGET(window), GTK_STYLE(style)); 
    gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER_ALWAYS); 
    gtk_container_set_border_width(GTK_CONTAINER(window), 0); 
    //gtk_window_set_resizable(GTK_WINDOW(window), (gboolean) FALSE); 
    gtk_window_set_decorated(GTK_WINDOW(window), FALSE);  

    return(window); 
} 

int main (int argc, char *argv[]) 
{ 
    GdkPixbufAnimation *animation; 
    GtkWidget *image; 
    int x,y;  
    GdkPixbuf *pixBuf; 
    GdkPixmap *pixMap; 
    gchar filename[20]; 
    GtkWidget *btnSpin, *btnExit; 

    GtkWidget *frame;  /* for absolute positionining of widgets */ 
    GtkWidget *window; 
    int posx, posy; 

    gtk_init (&argc, &argv); 

    window = SetupWindow("Demo", "background.gif"); 
    g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); 

    frame = gtk_fixed_new(); 
    gtk_container_add(GTK_CONTAINER(window), frame); 

    btnSpin = gtk_button_new_with_label("Spin"); 
    gtk_widget_set_size_request(btnSpin, 80, 35); 
    gtk_fixed_put(GTK_FIXED(frame), btnSpin, 229, 485); 
    g_signal_connect(G_OBJECT(btnSpin), "clicked", G_CALLBACK(btnSpin_clicked), NULL); 

    btnExit = gtk_button_new_with_label("Exit"); 
    gtk_widget_set_size_request(btnExit, 80, 35); 
    gtk_fixed_put(GTK_FIXED(frame), btnExit, 320, 485); 
    g_signal_connect(G_OBJECT(btnExit), "clicked", G_CALLBACK(btnExit_clicked), NULL); 

    /* setup animated gifs */ 
    for(y = 0; y < 3; y++) 
    { 
     posy = (y*120) + 20; 
     for(x = 0; x < 5; x++) 
     { 
      posx = (x*120) + 20; 
      /* set each Image widget to spin GIF */ 
      sprintf(filename,"%d-%d.gif", y+1,x+1); 
      images[y][x] = gtk_image_new_from_file(filename); 
      gtk_fixed_put(GTK_FIXED(frame), images[y][x], posx, posy); 
     } 
    } 

    gtk_widget_show_all(window); 

    gtk_main(); 

    return 0; 
} 
+2

Я не уверен, что вы действительно можете это сделать ... – ptomato

+0

Спасибо ptomato. Надеюсь, это возможно. – Chimera

+1

Трудно сказать, что такое анимация на самом деле, документация немного наклонена. Либо экспериментируйте с ним немного, либо попытайтесь найти какой-то код, который его использует, и посмотрите, как они это делают ... – ptomato

ответ

4

После взглянуть на GtkImage source code, я боюсь, что нет никакого сигнала, который генерируется, когда анимация завершена. Однако вы можете перезапустить анимацию, вызвав gtk_image_set_from_file() или gtk_image_set_from_animation().

Чтобы полностью решить вашу первоначальную проблему, я предлагаю создать подкласс GtkImage. Он должен вести себя точно так же, как GtkImage, за исключением того, что animation_timeout должен отправить сигнал, если delay < 0 около line 1315.

Информация о создании подкласса GObject (обратите внимание, что GtkImage является GObject) можно найти here.

+0

Спасибо. Пока что я решил просто повторно вызвать gtk_image_set_from_file(), который заставляет анимацию перезапускаться. Однако это неоптимально. Я не могу поверить, что нет возможности перезапустить анимацию, не прибегая к такому радикальному и неэффективному методу. – Chimera

+0

Хотел бы я принять ваш ответ и дать вам 100 репутацию, потому что, очевидно, вы потратили некоторое время на эту проблему для меня. Есть ли способ, которым я могу просто дать вам некоторую репутацию, поскольку вы частично ответили на мои вопросы? – Chimera

+0

Ну, если ответ получает 2 upvotes, и вы его не принимаете, я получаю 50 очков после истечения срока действия бонуса. В любом случае, спасибо за внимание. – user1202136

0

Основываясь на ответе user1202136, приведенные ниже фрагменты кода показывают решение. Я публикую это, если другие считают это полезным.

Основная идея заключается в том, чтобы использовать GdkPixbufAnimation, gdk_pixbuf_animation_new_from_file и gtk_image_set_from_animation

Следующий фрагмент кода (s) показать, как это сделать.

GtkWidget *images[3][5]; 
GdkPixbufAnimation *animations[3][5]; 

/* Initial setup of animated gifs */ 
for(y = 0; y < 3; y++) 
{ 
    for(x = 0; x < 5; x++) 
    { 
     /* set each Image widget to spin GIF */ 
     sprintf(filename,"%d-%d.gif", y+1,x+1); 
     images[y][x] = gtk_image_new(); 
     animations[y][x] = gdk_pixbuf_animation_new_from_file (filename , &error); 
     gtk_image_set_from_animation (GTK_IMAGE(images[y][x]), animations[y][x]); 
     gtk_fixed_put(GTK_FIXED(frame), images[y][x], (x*120) + 20, (y*120) + 20); 
    } 
} 


/* now to restart the animations use the images and animations array already stored in memory, 
    no need to re-read the animations from disk so this happens quickly 
*/ 

/* restart animated gifs */ 
for(y = 0; y < 3; y++) 
{ 
    for(x = 0; x < 5; x++) 
    { 
     gtk_image_set_from_animation(GTK_IMAGE(images[y][x]), animations[y][x]); 
    } 
} 
Смежные вопросы