【问题标题】:Rotate Image Gtk 3 with cairo用 cairo 旋转图像 Gtk 3
【发布时间】:2018-04-11 23:35:08
【问题描述】:

我正在尝试在随机位置获取图像以进行旋转。我在看另一个类似的帖子(rotate image)。但我无法让事情正常进行。

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

GtkWidget *window;

static void rotate_cb()
{
    gtk_widget_queue_draw(window);

}

static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
    GtkWidget *img = (GtkWidget *)(data);
    gint w = gtk_widget_get_allocated_width (img);
    gint h = gtk_widget_get_allocated_height (img);
    gtk_widget_realize(img);
    cairo_surface_t *surface = gdk_window_create_similar_surface(gtk_widget_get_window (img), CAIRO_CONTENT_COLOR, w, h);
    cairo_t *cr = cairo_create (surface);

    cairo_translate(cr, w/2, h/2);
    cairo_rotate(cr, 2);
    cairo_set_source_surface(cr, surface, -w/2, -h/2);

    cairo_paint(cr);
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
    return FALSE;
}


int main(int argc, char *argv[])
{   
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 600, 600);
    gtk_widget_set_app_paintable(window, TRUE);
    GtkWidget *l = gtk_layout_new(NULL, NULL);
    gtk_container_add(GTK_CONTAINER(window), l);
    GtkWidget *img = gtk_image_new_from_file("example.png");
    gtk_layout_put(GTK_LAYOUT(l), img, 300, 300);

    g_signal_connect(window, "draw", G_CALLBACK (on_expose_event), img);
    g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL);

    GtkWidget *button = gtk_button_new_with_label("button");
    g_signal_connect(button, "clicked", G_CALLBACK(rotate_cb), NULL);
    gtk_layout_put(GTK_LAYOUT(l), button, 0, 0);

    gtk_widget_show_all(window);
    gtk_main();
}

窗口确实收到了draw信号,但我不知道如何连接gtkwidget和cairo_surface_t。

或者也许有更好的方法来做到这一点(没有 cairo)。我更喜欢各种想法!谢谢!

【问题讨论】:

    标签: gtk3 cairo


    【解决方案1】:

    GtkWidget draw 信号处理程序原型应该是:

    gboolean user_function (GtkWidget *widget, CairoContext *cr, gpointer user_data)
    

    documentation中所述:

    当小部件应该呈现自身时会发出此信号。这 小部件的左上角必须绘制在传递的原点 在上下文中并根据返回的值调整大小 gtk_widget_get_allocated_width() 和 gtk_widget_get_allocated_height()。

    连接到此信号的信号处理程序可以修改 cairo 上下文 以他们喜欢的任何方式作为 cr 传递,不需要恢复它。这 信号发射负责调用 cairo_save() 之前和 调用处理程序后的 cairo_restore()。

    信号处理程序将获得一个 cr,其中剪辑区域已设置为 小部件的脏区域,即需要重新绘制的区域。 想要避免完全重绘自己的复杂小部件 可以获得剪辑区域的完整范围 gdk_cairo_get_clip_rectangle(),或者他们可以获得更细粒度的 脏区的表示 cairo_copy_clip_rectangle_list()。参数

    widget - 接收信号的对象

    cr - 要绘制到的 cairo 上下文

    user_data - 连接信号处理程序时的用户数据集。

    所以您的on_expose_event 函数原型必须更改,并且将向您提供 cairo 上下文:

    static gboolean on_expose_event(GtkWidget *widget, cairo_t *cr, gpointer data)
    {
    .... // your code must change too
    }
    

    【讨论】:

    • 那么在这种情况下,我是在整个窗口上创建一个 cairo 表面还是只在我想要旋转的小部件上创建一个?
    • 如果它有一个 GdkWindow,它将返回你连接信号的小部件的 cairo 上下文
    • @AndrewShao 你不需要创建一个......回调给你一个可以使用
    • 使用来自 GtkWindow 的不是最好的选择,例如使用 GtkDrawingArea。
    • 谢谢!我试试看!
    猜你喜欢
    • 2012-06-14
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多