使用GTK + 2和Cairo进行非常简单的平滑动画

时间:2014-04-04 00:47:41

标签: c animation gtk cairo gtk2

我使用gtk + 2.0和cairo。我写了一个打开窗口的简单程序 移动一点。一个简单的biliard,只有水平运动。这只是一个考验。

问题是它似乎不那么顺利,我会问是否存在 这里有一些gtk或cairo专家可以检查代码中的错误。

感谢。

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

gboolean timeout(gpointer data)
{
    GtkWidget *widget = GTK_WIDGET(data);
    if (!widget->window) return TRUE;
    gtk_widget_queue_draw(widget);
}

gboolean configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
{ 
    return TRUE;
}

double px = 10;
double vx = **2**;

gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
    cairo_t *cr = gdk_cairo_create(widget->window);
    cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height);
    cairo_clip(cr);

    cairo_set_source_rgb(cr,1,0,0);
    cairo_arc(cr, px, 100, 6, 0, 2*M_PI);
    cairo_fill(cr);
    cairo_set_source_rgb(cr,0,0,0);
    cairo_destroy(cr);

    if (px <= 3 || px >= 200-3) vx = -vx;
    px += vx;
    return FALSE;
}

int main(int argc, char *argv[])
{
    char *title = "Test";
    int sx = 200;
    int sy = 200;

    gtk_init(NULL,NULL);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window),title);
    gtk_container_set_border_width(GTK_CONTAINER (window), 2);

    g_signal_connect(window, "destroy",G_CALLBACK(gtk_main_quit),&window);
    GtkWidget *drawing_area = gtk_drawing_area_new();
    //g_signal_connect(window,"key-press-event",G_CALLBACK(on_key_press),NULL);

    const GdkColor bianco = { 0, 0xffff, 0xffff, 0xffff };
    const GdkColor nero = { 0, 0x0, 0x0, 0x0 };
    gtk_widget_modify_bg(drawing_area, GTK_STATE_NORMAL, &bianco);

    gtk_widget_set_size_request(drawing_area, sx, sy);

    g_signal_connect(drawing_area,"configure_event",G_CALLBACK(configure), NULL);
    g_signal_connect(drawing_area,"expose_event",G_CALLBACK(expose),NULL);

    gtk_container_add(GTK_CONTAINER(window), drawing_area);
    gtk_widget_show(drawing_area);

    g_timeout_add(**10**, timeout, window);

    if (!GTK_WIDGET_VISIBLE (window))
        gtk_widget_show_all(window);
    else {
        gtk_widget_destroy (window);
        window = NULL;
    }

    gtk_main();
    return 0;
}

1 个答案:

答案 0 :(得分:1)

不太顺利?好吧,在100毫秒的时间内,你每秒最多可以画10帧,难怪它不顺畅......你应该瞄准60 fps。此外,您通过调用gtk_widget_queue_draw使整个小部件无效,因此您对cairo_clip的调用通常是无用的,因为剪切区域是整个小部件。你应该调用gtk_widget_queue_draw_area,这样你的裁剪区域很有用,并通过在 n n-1 的帧保留动画记录来确定区域,因此你重绘两个区域避免前一帧未被删除。

Owen Tailor博客上有许多关于动画感知的有趣内容,从这篇文章开始,更近期:

http://blog.fishsoup.net/2009/05/28/frames-not-idles/

查看所有带有数字的帖子,它是一个金矿。