首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用GTK+ / Cairo旋转图像

如何使用GTK+ / Cairo旋转图像
EN

Stack Overflow用户
提问于 2012-06-12 03:14:26
回答 2查看 6.8K关注 0票数 2

我有一个简单的应用程序,它应该使用GTK+Cairo将装饰过的轮子每x毫秒旋转这么多度。我在下面有一些代码,可以从计时器调用cairo_rotate()。但是,图像不会改变。是否必须使图像无效才能触发expose-event?我对Cairo非常陌生,如果有一个简单的例子演示如何在GTK+中使用Cairo旋转图像,我将不胜感激。

代码语言:javascript
运行
复制
#include <cairo.h>
#include <gtk/gtk.h>

cairo_surface_t *image;
cairo_t *cr;


gboolean rotate_cb( void )
{

    cairo_rotate (cr, 1);
    //cairo_paint(cr);
    printf("rotating\n");

    return( TRUE );
}

static gboolean
on_expose_event(GtkWidget *widget,
    GdkEventExpose *event,
    gpointer data)
{
  cr = gdk_cairo_create (widget->window);

  cairo_set_source_surface(cr, image, 0, 0);
  cairo_paint(cr);
  printf("Paint\n");

  //cairo_destroy(cr);

  return FALSE;
}


int main(int argc, char *argv[])
{
  GtkWidget *window;

  image = cairo_image_surface_create_from_png("wheel.png");

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  g_signal_connect(window, "expose-event",
      G_CALLBACK (on_expose_event), NULL);
  g_signal_connect(window, "destroy",
      G_CALLBACK (gtk_main_quit), NULL);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 500, 500); 
  gtk_widget_set_app_paintable(window, TRUE);

  gtk_widget_show_all(window);
  g_timeout_add(500, (GSourceFunc) rotate_cb, NULL);

  gtk_main();
  cairo_destroy(cr);
  cairo_surface_destroy(image);

  return 0;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-12 08:18:13

您需要将旋转存储在一个变量中,并在绘制之前将cairo_rotate(cr,rotation_amt);调用到on_expose_event方法中。

如果图像居中,还可以平移到窗口的中心,旋转并平移回来,以使轮子围绕其中心旋转。

代码语言:javascript
运行
复制
cairo_translate(cr, width / 2.0, height / 2.0);
cairo_rotate(cr, rotation_amt);
cairo_translate(cr, - image_w / 2.0, - image_h / 2.0);
cairo_set_source_surface(cr, image, 0, 0);
cairo_paint(cr);

我希望这是对的。

正如ptomato所说,您需要通过从rotate_cb调用gtk_widget_queue_draw来使您的绘图图面无效。而且为Cairo上下文保留一个全局变量是多余的。图像不会旋转,因为新创建的上下文加载了一个单位矩阵,并且您之前的所有变换都被重置。

票数 7
EN

Stack Overflow用户

发布于 2012-06-13 00:50:34

在cairo邮件列表的帮助下,这是一个有效的示例。我将这篇文章分享给那些可能觉得这篇文章有用的人。

代码语言:javascript
运行
复制
#include <cairo.h>
#include <gtk/gtk.h>
#include <math.h>
#include <stdlib.h> 

cairo_surface_t *image;
cairo_t *cr;
gdouble rotation = 0;
GtkWidget *window;

gint image_w, image_h;
double DegreesToRadians( int degrees );


double DegreesToRadians( int degrees )
{
    return((double)((double)degrees * ( M_PI/180 )));
}


gboolean rotate_cb( void *degrees )
{
    // Any rotation applied to cr here will be lost, as we create
    // a new cairo context on every expose event
    //cairo_rotate (cr, 4);
    rotation += DegreesToRadians((*(int*)(degrees)));
    //cairo_paint(cr);
    //      printf("rotating\n");
    // Tell our window that it should repaint itself (ie. emit an expose event)
    gtk_widget_queue_draw(window);

    return( TRUE );
}

static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event,gpointer data)
{
    // Make sure our window wasn't destroyed yet
    // (to silence a warning)
    g_return_if_fail(GTK_IS_WIDGET(widget));

    cr = gdk_cairo_create (widget->window);
    // We need to apply transformation before setting the source surface
    // We translate (0, 0) to the center of the screen,
    // so we can rotate the image around its center point,
    // not its upper left corner
    cairo_translate(cr, image_w/2, image_h/2);
    cairo_rotate(cr, rotation);
    cairo_set_source_surface(cr, image, -image_w/2, -image_h/2);
    // We need to clip around the image, or cairo will paint garbage data
    //cairo_rectangle(cr, -image_w/2, -image_h/2, image_w, image_h);
    //cairo_clip(cr);

    cairo_paint(cr);
    //printf("Paint\n");
    cairo_destroy(cr);
    return FALSE;
}


int main(int argc, char *argv[])
{   
    int degrees = 10, speed = 125;
    image = cairo_image_surface_create_from_png("wheel.png");
    image_w = cairo_image_surface_get_width(image);
    image_h = cairo_image_surface_get_height(image);

    gtk_init(&argc, &argv);

    if( argc == 3 )
    {
        degrees = atoi(argv[1]);
        speed = atoi(argv[2]);
    }


    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    g_signal_connect(window, "expose-event",
    G_CALLBACK (on_expose_event), NULL);
    g_signal_connect(window, "destroy",
    G_CALLBACK (gtk_main_quit), NULL);

    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), image_w, image_h);
    gtk_widget_set_app_paintable(window, TRUE);

    gtk_widget_show_all(window);
    g_timeout_add(speed, (GSourceFunc) rotate_cb, (void *)&degrees);

    gtk_main();
    cairo_surface_destroy(image);

    return 0;
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10986142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档