Gtk3和cairo g#u timeout#u add不';行不通

Gtk3和cairo g#u timeout#u add不';行不通,c,gtk3,cairo,C,Gtk3,Cairo,我用gtk3和cairo制作了非常简单的动画。我得到了g\u timeout\u add,它应该每隔1ms调用draw函数,但是它调用draw的速度要慢得多。为什么会发生这种情况,我该如何解决 #include <gtk/gtk.h> #include <cairo.h> gboolean timeout(GtkWidget *widget) { gtk_widget_queue_draw(widget); return TRUE; } void dr

我用gtk3和cairo制作了非常简单的动画。我得到了
g\u timeout\u add
,它应该每隔1ms调用
draw
函数,但是它调用
draw
的速度要慢得多。为什么会发生这种情况,我该如何解决

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

gboolean timeout(GtkWidget *widget)
{
    gtk_widget_queue_draw(widget);
    return TRUE;
}

void draw(GtkWidget* widget, cairo_t* cr)
{
    static int width, height,
               posX = 0,
               vX = 1;

    GtkWidget* window = gtk_widget_get_toplevel(widget);
    gtk_window_get_size(GTK_WINDOW(window), &width, &height);

    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_set_line_width(cr, 1);

    cairo_rectangle(cr, posX, height/2, 1, 1);
    cairo_stroke(cr);

    if(posX + vX >= width || posX + vX == 0)
        vX = -vX;
    posX += vX;
}

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

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    darea = gtk_drawing_area_new();

    gtk_container_add(GTK_CONTAINER(window), darea);

    gtk_window_set_default_size(GTK_WINDOW(window), 500, 400);

    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(draw), NULL);

    g_timeout_add(1, (GSourceFunc)timeout, window);

    gtk_widget_show_all(window);
    gtk_main();
}
#包括
#包括
gboolean超时(GtkWidget*小部件)
{
gtk_小部件_队列_绘制(小部件);
返回TRUE;
}
无效绘制(GtkWidget*小部件,cairo_t*cr)
{
静态整数宽度,高度,
posX=0,
vX=1;
GtkWidget*窗口=gtk_小部件_获取_顶层(小部件);
gtk_窗尺寸(gtk_窗(窗)、宽度和高度);
cairo\u set\u source\u rgb(cr,0,0,0);
cairo_集_线_宽(cr,1);
cairo_矩形(cr,posX,高度/2,1,1);
脑卒中(cr);
如果(posX+vX>=宽度| | posX+vX==0)
vX=-vX;
posX+=vX;
}
int main(int argc,字符**argv)
{
GtkWidget*窗口;
GtkWidget*darea;
gtk_init(&argc,&argv);
窗口=gtk_窗口_新建(gtk_窗口_顶层);
darea=gtk_图纸_区域_新();
gtk_容器添加(gtk_容器(窗口),darea);
gtk_窗口设置默认大小(gtk_窗口(窗口),500,400);
g_信号连接(g_对象(窗口),“销毁”,g_回调(gtk_主退出),NULL);
g_信号连接(g_对象(darea),“绘制”,g_回调(绘制),空);
g_timeout_add(1,(GSourceFunc)超时,窗口);
gtk_小部件_全部显示(窗口);
gtk_main();
}

根据GLib关于
g\u timeout\u add()的文档


由于事件循环正在为您的应用程序执行其他操作(包括运行
draw()
函数),因此超时可能无法跟上1ms的节拍,当然不应该依赖它来精确计时。

根据GLib的
g\u timeout\u add()文档:

因为事件循环正在为您的应用程序执行其他操作(包括运行
draw()
函数),所以超时可能无法跟上1ms的节拍,当然不应该依赖它来精确计时

为什么会发生,以及

Zrax对此作出了回答。我只想添加一些东西:我在draw函数中添加了以下内容(并添加了相应的include)

我得到如下输出:

1518869317.202412
1518869317.218970
1518869317.236563
1518869317.253032
1518869317.269721
1518869317.286305
因此,draw函数大约每17毫秒调用一次,或每秒调用60次

我怎样才能修好它

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

gboolean timeout(GtkWidget *widget)
{
    gtk_widget_queue_draw(widget);
    return TRUE;
}

void draw(GtkWidget* widget, cairo_t* cr)
{
    static int width, height,
               posX = 0,
               vX = 1;

    GtkWidget* window = gtk_widget_get_toplevel(widget);
    gtk_window_get_size(GTK_WINDOW(window), &width, &height);

    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_set_line_width(cr, 1);

    cairo_rectangle(cr, posX, height/2, 1, 1);
    cairo_stroke(cr);

    if(posX + vX >= width || posX + vX == 0)
        vX = -vX;
    posX += vX;
}

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

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    darea = gtk_drawing_area_new();

    gtk_container_add(GTK_CONTAINER(window), darea);

    gtk_window_set_default_size(GTK_WINDOW(window), 500, 400);

    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(draw), NULL);

    g_timeout_add(1, (GSourceFunc)timeout, window);

    gtk_widget_show_all(window);
    gtk_main();
}
这就提出了一个问题:你为什么要画的速度超过60帧

如何创建一个
GTimer
并使用
g\u timer\u appeased()
来确定必须在哪里绘制?也就是说,不要假设您绘制的速度足够快,而是在每次绘制时计算当前图形状态

为什么会发生,以及

Zrax对此作出了回答。我只想添加一些东西:我在draw函数中添加了以下内容(并添加了相应的include)

我得到如下输出:

1518869317.202412
1518869317.218970
1518869317.236563
1518869317.253032
1518869317.269721
1518869317.286305
因此,draw函数大约每17毫秒调用一次,或每秒调用60次

我怎样才能修好它

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

gboolean timeout(GtkWidget *widget)
{
    gtk_widget_queue_draw(widget);
    return TRUE;
}

void draw(GtkWidget* widget, cairo_t* cr)
{
    static int width, height,
               posX = 0,
               vX = 1;

    GtkWidget* window = gtk_widget_get_toplevel(widget);
    gtk_window_get_size(GTK_WINDOW(window), &width, &height);

    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_set_line_width(cr, 1);

    cairo_rectangle(cr, posX, height/2, 1, 1);
    cairo_stroke(cr);

    if(posX + vX >= width || posX + vX == 0)
        vX = -vX;
    posX += vX;
}

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

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    darea = gtk_drawing_area_new();

    gtk_container_add(GTK_CONTAINER(window), darea);

    gtk_window_set_default_size(GTK_WINDOW(window), 500, 400);

    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(draw), NULL);

    g_timeout_add(1, (GSourceFunc)timeout, window);

    gtk_widget_show_all(window);
    gtk_main();
}
这就提出了一个问题:你为什么要画的速度超过60帧


如何创建一个
GTimer
并使用
g\u timer\u appeased()
来确定必须在哪里绘制?也就是说,不必假设您的绘图速度足够快,您只需在每次绘图时计算当前图形状态。

但它的工作速度要慢得多,不会延迟1毫秒或5毫秒,至少慢50倍。这是不正常的。但它的工作速度要慢得多,它不会延迟1毫秒或5毫秒,至少慢50倍。这不正常。非常感谢你,现在我明白了!非常感谢,现在我明白了!