当我调整GtkWindow的大小时,我希望GtkImage也可以调整大小,同时保持与以前相同的宽高比。 关于如何使用GTK3
进行设置,我找不到任何好的例子这是我到目前为止所尝试的:
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
GtkAllocation *allocation = g_new0 (GtkAllocation, 1);
gboolean resize_image(GtkWidget *widget, GdkEvent *event, GtkWidget *window) {
GdkPixbuf *pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(widget));
if (pixbuf == NULL) {
g_printerr("Failed to resize image\n");
return 1;
}
gtk_widget_get_allocation(GTK_WIDGET(widget), allocation);
pixbuf = gdk_pixbuf_scale_simple(pixbuf, widget->allocation.width, widget->allocation.height, GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(widget), pixbuf);
return FALSE;
}
int main(int argc, char **argv) {
GtkWidget *window = NULL;
GtkWidget *image = NULL;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
image = gtk_image_new_from_file("image.jpg");
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(image, "draw", G_CALLBACK(resize_image), (gpointer)window);
gtk_container_add(GTK_CONTAINER(window), image);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}
此代码应该只是将Pixbuf的大小调整为父级的大小,但它不起作用,我得到这些错误:
GdkPixbuf-CRITICAL **:gdk_pixbuf_get_width:断言'GDK_IS_PIXBUF (pixbuf)'失败
GLib-GObject-CRITICAL **:g_object_unref:断言'G_IS_OBJECT (对象)'失败
即使这段代码有效,我也无法保持相同的宽高比,如何实现这一目标?
先谢谢
答案 0 :(得分:1)
嗯,这样做的一个技巧是在图像和窗口之间使用GtkLayout。
另外,请使用draw
信号,而不是使用size-allocate
信号。
我们将加载一个GdkPixbuf并将其用作缩放的参考,否则质量会因累积'调整大小'而恶化。
一个简单的方法是:
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
struct _resize_widgets {
GtkWidget *image;
GdkPixbuf *pixbuf;
};
typedef struct _resize_widgets ResizeWidgets;
gboolean resize_image(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data) {
int x,y,w,h;
GdkPixbuf *pxbscaled;
GtkWidget *image = (GtkWidget *) ((ResizeWidgets *) user_data)->image;
GdkPixbuf *pixbuf= (GdkPixbuf *) ((ResizeWidgets *) user_data)->pixbuf;
x = 0;
y = 0;
h = allocation->height;
w = (gdk_pixbuf_get_width(pixbuf) * h) / gdk_pixbuf_get_height(pixbuf);
pxbscaled = gdk_pixbuf_scale_simple(pixbuf, w, h, GDK_INTERP_BILINEAR);
if (w < allocation->width) {
x = (allocation->width - w) / 2;
gtk_layout_move(GTK_LAYOUT(widget), image, x, y);
}
gtk_image_set_from_pixbuf(GTK_IMAGE(image), pxbscaled);
g_object_unref (pxbscaled);
return FALSE;
}
int main(int argc, char **argv) {
GtkWidget *window = NULL;
GtkWidget *image = NULL;
GtkWidget *container = NULL;
GdkPixbuf *pixbuf = NULL;
ResizeWidgets *widgets;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
container = gtk_layout_new(NULL, NULL);
image = gtk_image_new();
pixbuf = gdk_pixbuf_new_from_file ("image.png", NULL);
if (pixbuf == NULL) {
g_printerr("Failed to resize image\n");
return 1;
}
widgets = g_new0(ResizeWidgets, 1);
widgets->image = image;
widgets->pixbuf = pixbuf;
gtk_container_add(GTK_CONTAINER(window), container);
gtk_layout_put(GTK_LAYOUT(container), image, 0, 0);
gtk_widget_set_size_request (GTK_WIDGET(window), 20, 20);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(container, "size-allocate", G_CALLBACK(resize_image), widgets);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
g_object_unref (pixbuf);
g_free(widgets);
return 0;
}
编译gcc -o main main.c
pkg-config --cflags --libs gtk + -3.0`
这将保持纵横比。如果不需要,那么resize_image
回调处理程序将是:
gboolean resize_image(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data) {
int x,y,w,h;
GdkPixbuf *pxbscaled;
GtkWidget *image = (GtkWidget *) ((ResizeWidgets *) user_data)->image;
GdkPixbuf *pixbuf= (GdkPixbuf *) ((ResizeWidgets *) user_data)->pixbuf;
pxbscaled = gdk_pixbuf_scale_simple(pixbuf, allocation->width, allocation->height, GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(image), pxbscaled);
g_object_unref (pxbscaled);
return FALSE;
}
这是一个简单的黑客攻击,显然还有其他选择,例如用于绘制的cairo或只是检查更完整的Eye of Gnome (eog)实现。