C Gtk3和开罗动画抽搐
我用gtk3和cairo制作了一个非常简单的动画。每隔一秒钟它就会有点抽搐。这真的很烦人,而且看起来不太好。为什么会发生这种情况,我该如何解决C Gtk3和开罗动画抽搐,c,gtk,gtk3,cairo,C,Gtk,Gtk3,Cairo,我用gtk3和cairo制作了一个非常简单的动画。每隔一秒钟它就会有点抽搐。这真的很烦人,而且看起来不太好。为什么会发生这种情况,我该如何解决 #include <gtk/gtk.h> #include <cairo.h> static int width, height, posX = 0, vX = 2; gboolean draw(GtkWidget* widget, cairo_t* cr) { GtkWidg
#include <gtk/gtk.h>
#include <cairo.h>
static int width, height,
posX = 0,
vX = 2;
gboolean draw(GtkWidget* widget, cairo_t* cr)
{
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, 100);
cairo_rectangle(cr, posX, height/2, 100, 100);
cairo_stroke(cr);
if(posX + vX >= width || posX + vX == 0)
vX = -vX;
posX += vX;
gtk_widget_queue_draw(widget);
return TRUE;
}
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(16, (GSourceFunc)draw, window);
gtk_widget_show_all(window);
gtk_main();
}
#包括
#包括
静态整数宽度,高度,
posX=0,
vX=2;
gboolean绘图(GtkWidget*小部件,cairo_t*cr)
{
GtkWidget*窗口=gtk_小部件_获取_顶层(小部件);
gtk_窗尺寸(gtk_窗(窗)、宽度和高度);
cairo\u set\u source\u rgb(cr,0,0,0);
cairo\u set\u line\u width(cr,100);
cairo_矩形(cr,posX,高度/21000);
脑卒中(cr);
如果(posX+vX>=宽度| | posX+vX==0)
vX=-vX;
posX+=vX;
gtk_小部件_队列_绘制(小部件);
返回TRUE;
}
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_超时_添加(16,(GSourceFunc)绘图,窗口);
gtk_小部件_全部显示(窗口);
gtk_main();
}
<>代码>首先考虑你的原程序在我的系统上完美无瑕地工作,所以这对你的系统来说可能是个问题。您可以尝试提高程序的优先级,但基本上您的代码容易受到此类问题的影响:有关基本原理,请参阅
无论如何,还有一个概念上的问题:您正在使用draw()
做两件事。它用作draw
信号和超时回调。这是错误的:draw信号必须是幂等的,因为您不知道它被调用的时间和次数
下面是将原始函数拆分为move()
和draw()
的示例:
#包括
#包括
静态整数宽度,高度,
posX=0,
vX=2;
静态gboolean移动(GtkWidget*小部件)
{
GtkWidget*窗口=gtk_小部件_获取_顶层(小部件);
gtk_窗尺寸(gtk_窗(窗)、宽度和高度);
如果(posX+vX>=宽度| | posX+vX==0)
vX=-vX;
posX+=vX;
gtk_小部件_队列_绘制(小部件);
返回TRUE;
}
静态gboolean绘图(GtkWidget*小部件,cairo\u t*cr)
{
cairo\u set\u source\u rgb(cr,0,0,0);
cairo\u set\u line\u width(cr,100);
cairo_矩形(cr,posX+0.5,高度/2+0.51000);
脑卒中(cr);
返回FALSE;
}
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(16,(GSourceFunc)移动,窗口);
gtk_小部件_全部显示(窗口);
gtk_main();
}
不确定你的问题会得到解决,但无论如何都必须这样做。
< P>首先考虑你的原始程序在我的系统上完美无瑕地工作,所以这可能是你的系统中的一个问题。您可以尝试提高程序的优先级,但基本上您的代码容易受到此类问题的影响:有关基本原理,请参阅
无论如何,还有一个概念上的问题:您正在使用draw()
做两件事。它用作draw
信号和超时回调。这是错误的:draw信号必须是幂等的,因为您不知道它被调用的时间和次数
下面是将原始函数拆分为move()
和draw()
的示例:
#包括
#包括
静态整数宽度,高度,
posX=0,
vX=2;
静态gboolean移动(GtkWidget*小部件)
{
GtkWidget*窗口=gtk_小部件_获取_顶层(小部件);
gtk_窗尺寸(gtk_窗(窗)、宽度和高度);
如果(posX+vX>=宽度| | posX+vX==0)
vX=-vX;
posX+=vX;
gtk_小部件_队列_绘制(小部件);
返回TRUE;
}
静态gboolean绘图(GtkWidget*小部件,cairo\u t*cr)
{
cairo\u set\u source\u rgb(cr,0,0,0);
cairo\u set\u line\u width(cr,100);
cairo_矩形(cr,posX+0.5,高度/2+0.51000);
脑卒中(cr);
返回FALSE;
}
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(16,(GSourceFunc)移动,窗口);
gtk_小部件_全部显示(窗口);
gtk_main();
}
不确定您的问题是否会得到解决,但无论如何都必须这样做。我认为您的问题在于,您使用的是一个精确的计时源,而不是文档中所述的:
请注意,由于处理其他事件源,超时功能可能会延迟。因此,不应依赖它们来精确计时。每次调用timeout函数后,将根据当前时间和给定的间隔重新计算下一次超时的时间(它不会试图“赶上”延迟中丢失的时间)
这意味着每次调用时,draw
回调中的代码可能会稍晚(或更晚)调用。由于没有重新计算超时时间,错误加起来。你会失去同步,在错误的位置画图。例如,在视频播放器中,当一帧被解码时会发生这种情况:如果该帧需要太长的时间才能解码
#include <gtk/gtk.h>
#include <cairo.h>
static int width, height,
posX = 0,
vX = 2;
static gboolean move(GtkWidget* widget)
{
GtkWidget* window = gtk_widget_get_toplevel(widget);
gtk_window_get_size(GTK_WINDOW(window), &width, &height);
if(posX + vX >= width || posX + vX == 0)
vX = -vX;
posX += vX;
gtk_widget_queue_draw(widget);
return TRUE;
}
static gboolean draw(GtkWidget* widget, cairo_t* cr)
{
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 100);
cairo_rectangle(cr, posX + 0.5, height/2 + 0.5, 100, 100);
cairo_stroke(cr);
return FALSE;
}
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(16, (GSourceFunc)move, window);
gtk_widget_show_all(window);
gtk_main();
}