|
我要用Gtk实现一个模拟交通系统的动画,即车辆在十字路口会根据交通灯停下或者行驶。
我采用的方式是类似于VC下的动画制作方式,先在pixmap中将相关的图形绘制好,再在expose_event的处理函数中将pixmap贴上到drawing_area,驱动动画进行的是用idle回调函数,在idle回调函数中通过计数达到一定数值就执行相关的绘图函数(run,display_car,draw_background etc),当将所有的图形都重新绘制在pixmap中后就在run中调用 gtk_widget_queue_draw函数激发expose_event的事件,将pixmap贴上到drawing_area上面。
我遇到的问题是,我在run,display,draw_background里面在pixmap上绘图的图形完全显示了,但我用anjuta调试的时候的确是执行到这些函数里面的绘图语句,这个问题困扰多天了,恳请哪位高人能指点一二。是不是gtk的绘图机制有哪些地方要特别注意的...
在调试的时候终端会出现 gtk-critical...的提示,说 GDK_IS_GC**Failed
下面是相关的代码,下面的代码纯粹是一个框架,用于测试我这种方式实现的机制:
此处是定义的相关数据结构:(可忽略)
enum _CarDirection {RightToLeft,LeftToRight,UptoDown,DownToUp};
typedef enum _CarDirection CarDirection;
enum _LightState {Red,Mediate,Green};
typedef enum _LightState LightState;
struct _Car
{
gint speed;
CarDirection direction;
GdkPoint centralPoint;
};
typedef struct _Car Car;
struct _CarLink
{
Car car;
struct _CarLink *link;
};
typedef struct _CarLink CarLink;
struct _TrafficLight
{
LightState vertical;
LightState horizontal;
};
typedef struct _TrafficLight TrafficLight;
struct _Channel
{
CarLink* cars;
gint count;
};
typedef struct _Channel Channel;
struct _TrafficChannels
{
Channel righttoleft;
Channel lefttoright;
Channel uptodown;
Channel downtoup;
};
typedef struct _TrafficChannels TrafficChannels;
struct _EnvironmentViriable
{
gint tCheck;
gint iCarTotal;
gint iCarLength;
GdkGC *gc;
GdkGC *bgGC;
GtkWidget *da;
};
typedef struct _EnvironmentViriable EnvironmentViriable;
************************************************************
定义的测试全局变量:
GdkPixmap *pixmap=NULL;
EnvironmentViriable ev;
Car car;
*************************************************************
相关的函数:
//获取颜色,用于偷懒
GdkColor get_color(int red,int green,int blue)
{
GdkColor color;
color.red=red;
color.green=green;
color.blue=blue;
return color;
}
//退出的销毁函数
void destroy(GtkWidget *widget,gpointer data)
{
gtk_main_quit();
}
//相关变量初始化函数
void init(GtkWidget* widget)
{
GdkColor color=get_color(0,0,65535);
ev.tCheck=0;
ev.gc=gdk_gc_new(widget->window);
gdk_gc_set_rgb_fg_color(ev.gc,&color);
gdk_gc_set_rgb_bg_color(ev.gc,&color);
color=get_color(20000,20000,20000);
ev.bgGC=gdk_gc_new(widget->window);
gdk_gc_set_rgb_bg_color(ev.bgGC,&color);
car.centralPoint.x=0;
car.centralPoint.y=0;
ev.da=widget;
}
//简单地函数背景
void draw_background(GtkWidget* widget)
{
gdk_draw_rectangle(pixmap,ev.gc,TRUE,0,0,widget->allocation.width,widget->allocation.height);
}
//测试,用于绘制车辆
void display_car(GtkWidget* widget)
{
GdkColor color=get_color(30000,30000,65535);
gdk_gc_set_rgb_fg_color(ev.gc,&color);
gdk_draw_rectangle(pixmap,ev.gc,TRUE,car.centralPoint.x,300,10,10);
}
//运行函数
void run(GtkWidget* widget)
{
car.centralPoint.x+=15;
draw_background(widget);
display_car(widget);
gtk_widget_queue_draw(widget);
}
gboolean configure_event(GtkWidget *widget,GdkEventConfigure *event)
{
if(pixmap)
g_object_unref(pixmap);
pixmap=gdk_pixmap_new(widget->window,widget->allocation.width,widget->allocation.height,-1);
gdk_draw_rectangle(pixmap,widget->style->white_gc,TRUE,0,0,widget->allocation.width,widget->allocation.height);
return TRUE;
}
gboolean expose_event(GtkWidget *widget,GdkEventExpose *event,gpointer data)
{
gdk_draw_drawable(widget->window,widget->style->fg_gc[GTK_WIDGET_STATE(widget)],pixmap,event->area.x,event->area.y,event->area.x,event->area.y,event->area.width,event->area.height);
return FALSE;
}
//idle时候调用的回调函数
gint idle_callback(gpointer window)
{
ev.tCheck++;
if(ev.tCheck>20)
{
ev.tCheck=0;
run(ev.da);
}
return TRUE;
}
****************************************************************************************
main函数了
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *drawing_area;
GtkWidget *vbox;
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif
gtk_set_locale ();
gtk_init (&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window),"Linux Car");
gtk_widget_set_size_request(window,1000,700);
gtk_window_set_resizable(window,FALSE);
g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);
vbox=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show(vbox);
g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);
drawing_area=gtk_drawing_area_new();
gtk_drawing_area_size(GTK_DRAWING_AREA (drawing_area),1000,700);
gtk_box_pack_start(GTK_BOX(vbox),drawing_area,TRUE,TRUE,0);
gtk_widget_show(drawing_area);
g_signal_connect(G_OBJECT(drawing_area),"expose_event",G_CALLBACK(expose_event),NULL);
g_signal_connect(G_OBJECT(drawing_area),"configure_event",G_CALLBACK(configure_event),NULL);
gtk_widget_set_events(drawing_area,GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
init(drawing_area);
g_idle_add(idle_callback,(gpointer)drawing_area);
gtk_widget_show (window);
gtk_main ();
} |
|