gtk 显示修改后的图像
gtk display modified image
我正在更改图像的 pixbuf 数据以响应计时器事件,但只有在我用另一个 window 覆盖 window 然后再揭开它时才会出现更改。如何让更改在我做出更改后立即显示?
#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;
}
GtkImage
不是一般的绘图小部件,为此您需要 GtkDrawingArea
。我认为用 GtkImage
做你想做的最简单的方法是更新你的 GdkPixBuf
,然后用更新后的图像设置 GtkImage
。我已经增加了对 PixBuf
的引用计数,但我不是 100% 确定需要它,但它不会造成任何伤害。
#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;
}
我正在更改图像的 pixbuf 数据以响应计时器事件,但只有在我用另一个 window 覆盖 window 然后再揭开它时才会出现更改。如何让更改在我做出更改后立即显示?
#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;
}
GtkImage
不是一般的绘图小部件,为此您需要 GtkDrawingArea
。我认为用 GtkImage
做你想做的最简单的方法是更新你的 GdkPixBuf
,然后用更新后的图像设置 GtkImage
。我已经增加了对 PixBuf
的引用计数,但我不是 100% 确定需要它,但它不会造成任何伤害。
#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;
}