小小千想和您聊一聊

当前位置: 首页> 技术分享> GTK进阶学习:绘图事件一

GTK进阶学习:绘图事件一

  GTK界面只要有图片的地方,其底层实际上是通过绘图实现的,所以,我们很有必要学习一下绘图,这里我们使用 Cairo 进行相应的绘图操作。

  Cairo是用于绘制二维矢量图形的跨平台图形库,采用 C 语言实现,又被许多其它计算机语言所绑定。我们可以使用Cairo库在窗口中绘图,也可以用于生成PNG图片、PDF、PostScript、SVG文件。Cairo同时也是自由软件库,自GTK+2.8版本开始,Cairo成为GTK+库的一部分。

  绘图实际上也是事件的一种,GTK中,绘图事件也叫曝光事件。

  绘图时所触发的信号:expose-event

  只要触发曝光事件信号"expose-event",就会自动调用所连接的回调函数。

  这里需要注意的是,曝光事件信号 "expose-event" 默认的情况下,是自动触发的(当然也可以人为触发),就算我们不作任何操作,"expose-event"信号也有可能自动触发。前面我们学习中,我们按一下按钮就人为触发 "clicked" 信号,按一下鼠标人为触发 "button-press-event" 信号,如果我们不操作按钮,不操作鼠标,其对应的信号永远不会触发。

  曝光事件信号 "expose-event" 什么时候会自动触发呢?

  窗口状态(移动,初始化,按按钮……)改变,只用我们肉眼能看到窗口上有变化,它都会自动触发曝光事件信号"expose-event",然后就自动会调用它所连接的回调函数,但是,它不是刷新窗口的全部区域,它是按需要局部刷新,哪儿变化了就刷新那个变化的区域。

  当然我们也可以人为触发曝光事件信号"expose-event",并且指定刷图区域:

  触发信号,并且刷新图片的整个区域:

  void gtk_widget_queue_draw(GtkWidget *widget );

  widget:控件指针

  触发信号,并指定刷图区域:

  void gtk_widget_queue_draw_area(

  GtkWidget *widget,

  gint x,

  gint y,

  gint width,

  gint height);

  widget:控件指针

  x, y:刷图的起点坐标

  width, height:刷图的宽、高

  需要注意的是,我们绘图的操作不是写在任何函数都行,尽量在曝光事件信号 "expose-event" 所连接的回调函数里进行相应的绘图操作。

gboolean callback( GtkWidget *widget,       
GdkEventExpose *event, 
gpointer data )
{
// 绘图的相关操作
……
return FALSE; // 尽量返回FALSE
}

  如果窗口里有其它控件,回调函数必须返回FALSE,否则窗口里的控件会被绘图覆盖。

  使用 Cairo , 需要包含的头文件:#include 。

  创建Cairo环境:

  cairo_t *gdk_cairo_create( GdkDrawable *drawable );

  drawable:绘图区域

  返回值:cairo绘图环境指针

  注意:如果给窗口绘图,窗口本身不能绘图,窗口本质上是一个结构体,里面有个window成员,这个window成员才是真正的绘图区域。

  如:

  GtkWidget *w = gtk_window_new( GTK_WINDOW_TOPLEVEL );

  cairo_t *cr = gdk_cairo_create(w->window); // 注意传的参数

  回收资源:

  void cairo_destroy(cairo_t *cr);

  参数:cairo绘图环境指针

  设置画图的图片:

void gdk_cairo_set_source_pixbuf(
cairo_t *cr, 
const GdkPixbuf *pixbuf, 
double pixbuf_x, 
double pixbuf_y );
cr:cairo绘图环境指针
pixbuf:图片资源对象
pixbuf_x,pixbuf_y:画图的起点位置

  绘制设置好的图片:

  void cairo_paint(cairo_t *cr);

  cr:cairo绘图环境指针

  注意:如果绘制图片后想继续写字或画线,必须手动设置画笔颜色( cairo_set_source_rgb() ), 否则,字体或线条会被图片覆盖。

上一篇:HTML5工具初识之网页编辑器

下一篇:GTK进阶学习:事件盒子

QQ技术交流群

千锋物联网官方①群
858310440

加入群聊