【问题标题】:GTK3: Resize Image while retaining aspect-ratioGTK3:在保持纵横比的同时调整图像大小
【发布时间】:2018-05-14 08:36:40
【问题描述】:

当我调整 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 (对象)'失败

即使这段代码可以工作,我也无法保持相同的纵横比,如何实现这一点?

提前致谢

【问题讨论】:

    标签: c user-interface gtk gtk3


    【解决方案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.cpkg-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;
    }
    

    这是一个简单的 hack,显然还有其他选项,例如用于绘图的 cairo 或只是检查更完整的 Eye of Gnome (eog) 实现。

    【讨论】:

      猜你喜欢
      • 2013-06-26
      • 2012-04-15
      • 1970-01-01
      • 2012-05-01
      • 2012-11-15
      相关资源
      最近更新 更多