2017-04-02 4 views
0

타이머 이벤트에 대한 응답으로 이미지의 pixbuf 데이터를 변경하려고합니다. 예를 들어, 다른 윈도우로 창을 덮은 다음 변경 사항을 표시하는 경우에만 변경 사항이 나타납니다. 변경 사항을 적용하는 즉시 변경 사항을 표시하려면 어떻게해야합니까? 당신이 GtkDrawingArea을 필요 그것을 위해gtk 디스플레이 수정 된 이미지

#include <gtk/gtk.h> 
#include <stdlib.h> 

#define ROWS 400 
#define COLS 400 // must be divisible by 4 
#define BYTES_PER_PIXEL 3 

typedef struct { 
    GtkImage *image; 
    int stride; 
} ImageData; 

void free_pixels(guchar *pixels, gpointer data) { 
    free(pixels); 
} 

void setrgb(guchar *a, int row, int col, int stride, 
      guchar r, guchar g, guchar b) { 
    int p = row * stride + col * BYTES_PER_PIXEL; 
    a[p] = r; a[p+1] = g; a[p+2] = b; 
} 

int update_pic(gpointer data) { 
    static int row = 0; 
    if (row > 100) return FALSE; 

    ImageData *id = (ImageData*)data; 
    GdkPixbuf *pb = gtk_image_get_pixbuf(id->image); 
    guchar *g = gdk_pixbuf_get_pixels(pb); 

    for (int c = 0; c < 200; c++) 
    setrgb(g, row, c, id->stride, 255, 0, 0); 
    row++; 

    // this is not enough to get it to show the updated picture 
    gtk_widget_queue_draw(GTK_WIDGET(id->image)); 

    // adding this does not fix it 
    while (g_main_context_pending(NULL)) 
    g_main_context_iteration(NULL, FALSE); 

    return TRUE; 
} 

int main(int argc, char **argv) { 
    GtkWidget *window, *image; 
    GdkPixbuf *pb; 
    guchar *pixels = calloc(ROWS * COLS, BYTES_PER_PIXEL); 
    ImageData id; 

    gtk_init(&argc, &argv); 

    image = gtk_image_new(); 
    id.image = GTK_IMAGE(image); 
    id.stride = COLS * BYTES_PER_PIXEL; // COLS is divisible by 4 
    pb = gdk_pixbuf_new_from_data(
    pixels, 
    GDK_COLORSPACE_RGB,  // colorspace 
    0,      // has_alpha 
    8,      // bits-per-sample 
    COLS, ROWS,    // cols, rows 
    id.stride,    // rowstride 
    free_pixels,   // destroy_fn 
    NULL     // destroy_fn_data 
); 
    gtk_image_set_from_pixbuf(GTK_IMAGE(image), pb); 
    g_object_unref(pb); // should I do this? 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_title(GTK_WINDOW(window), "image"); 
    gtk_window_set_default_size(GTK_WINDOW(window), COLS, ROWS); 
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); 

    gtk_container_add(GTK_CONTAINER(window), image); 

    g_timeout_add(250,   // milliseconds 
       update_pic, // handler function 
       &id);  // data 

    gtk_widget_show_all(window); 
    gtk_main(); 

    return 0; 
} 
+0

IDK GTK이지만 일반적으로 어떤 종류의 "업데이트"이벤트를 창에 생성해야합니다. 가시 영역이 변경되면 일반적으로 창 관리자가이를 생성합니다. – Olaf

+0

이 질문은 어떤 용도로 사용됩니까? [새로 고침, gtk 창 (위젯) 다시 그리기 방법?] (http://stackoverflow.com/questions/32308231/how-to-refresh-redraw-a-window-widget-in-gtk) –

+0

여기에 또 다른 . [어떻게하면 GTK 3.8에서 화면 새로 고침을합니까?] (http://stackoverflow.com/questions/34912757/how-do-you-force-a-screen-refresh-in-gtk-3-8) –

답변

0

GtkImage는 일반적인 도면 위젯이 아니다. GtkImage으로 원하는 작업을 수행하는 가장 간단한 방법은 GdkPixBuf을 업데이트 한 다음 업데이트 된 이미지로 GtkImage을 설정하는 것입니다. 참조 횟수를 PixBuf으로 늘렸으나 필요하다고 확신하지는 못했지만 아무런 해를 끼치 지 않습니다.

#include <gtk/gtk.h> 
#include <stdlib.h> 

#define ROWS 400 
#define COLS 400 // must be divisible by 4 
#define BYTES_PER_PIXEL 3 

typedef struct { 
    GtkImage *image; 
    GdkPixbuf *pb; 
    int stride; 
} ImageData; 

void free_pixels(guchar *pixels, gpointer data) { 
    free(pixels); 
} 

void setrgb(guchar *a, int row, int col, int stride, 
      guchar r, guchar g, guchar b) { 
    int p = row * stride + col * BYTES_PER_PIXEL; 
    a[p] = r; a[p+1] = g; a[p+2] = b; 
} 

int update_pic(gpointer data) { 
    static int row = 0; 
    if (row > 100) return FALSE; 

    ImageData *id = (ImageData*)data; 
    guchar *g = gdk_pixbuf_get_pixels(id->pb); 

    for (int c = 0; c < 200; c++) 
    setrgb(g, row, c, id->stride, 255, 0, 0); 
    row++; 

    // Update the image, by setting it. 
    gtk_image_set_from_pixbuf(GTK_IMAGE(id->image), id->pb); 

    return TRUE; 
} 

int main(int argc, char **argv) { 
    GtkWidget *window; 
    guchar *pixels = calloc(ROWS * COLS, BYTES_PER_PIXEL); 
    ImageData id; 

    gtk_init(&argc, &argv); 

    id.stride = COLS * BYTES_PER_PIXEL; // COLS is divisible by 4 
    id.pb = gdk_pixbuf_new_from_data(
    pixels, 
    GDK_COLORSPACE_RGB,  // colorspace 
    0,      // has_alpha 
    8,      // bits-per-sample 
    COLS, ROWS,    // cols, rows 
    id.stride,    // rowstride 
    free_pixels,   // destroy_fn 
    NULL     // destroy_fn_data 
); 
    id.image = GTK_IMAGE(gtk_image_new_from_pixbuf(id.pb)); 
    g_object_ref(id.pb); 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_title(GTK_WINDOW(window), "image"); 
    gtk_window_set_default_size(GTK_WINDOW(window), COLS, ROWS); 
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); 

    gtk_container_add(GTK_CONTAINER(window), image); 

    g_timeout_add(250,   // milliseconds 
       update_pic, // handler function 
       &id);  // data 

    gtk_widget_show_all(window); 
    gtk_main(); 

    g_object_unref(id.pb); 

    return 0; 
}