绘图区构件和绘图@GTK+ 2.0 中文教程连载

绘图区构件和绘图

现在,我们开始向屏幕绘图。我们使用的构件是绘图区构件。一个绘图区构件本质上是一个 X 窗口,没有其它的东西。它是一个空白的画布,我们可以在其上绘制需要的东西。一个绘图区构件用如下函数创建:

GtkWidget* gtk_drawing_area_new        (void);

用如下函数设置构件的默认大小:

void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
gint width,
gint height);

当调用函数gtk_widget_set_size_request() 或用户手动调整包含绘图区的窗口的大小时,默认大小可以无效,这对所有的构件都是一样的。

当我们创建绘图区构件时应该注意,我们完全 负责绘制其上的内容。如果我们的窗口被遮住后暴露出来,我们得到一个暴露事件,我们必须重绘先前被遮住的部分。

为了能正确的重绘,我们必须记住绘制在屏幕上的内容。另外,这显然很麻烦,如果窗口的一部分被清除了,我们需一步步的重绘。解决的办法是使用一个后端位图 。我们用向图像中绘制来代替直接向屏幕绘制,当图像改变或图像的一部分需要显示,我们复制相应的部分到屏幕上。

用如下函数创建后端位图:

GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
gint width,
gint height,
gint depth);

window 参数设置一个 GDK 窗口,位图继承该窗口的所有属性。widthheight 设置位图的大小。depth 设置颜色深度 ,那是每个象素的二进制位数,如果depth设为-1 ,它会自动匹配窗口的颜色深度。

我们在事件"configure_event"的处理函数中创建位图。这个事件会在我们改变窗口大小时产生,包括窗口创建时。

/* 绘制区的后端位图 */
static GdkPixmap *pixmap = NULL;

/* 创建一个适当大小的后端位图 */
static gint
configure_event (GtkWidget *widget, GdkEventConfigure *event)
{
if (pixmap)
gdk_pixmap_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;
}

调用函数gdk_draw_rectangle() 清除位图,并初始化为白色。后面我们会详细讲解。

我们的暴露事件处理函数只是简单复制相应部分的位图到屏幕上(用暴露事件的event->area来确定重绘区域):

/* 从后端位图重新绘制屏幕 */
static gint
expose_event (GtkWidget *widget, GdkEventExpose *event)
{
gdk_draw_pixmap(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;
}

现在我们来看如何保持屏幕跟随位图的更新,如何在位图上绘制我们需要的东西? GTK 的GDK库中有许多函数用于在可绘区域 绘图。可绘区域可以是窗口、位图或黑白图。在上面我们已经见到了两个,gdk_draw_rectangle()gdk_draw_pixmap() 。这些函数的完全列表如下:

gdk_draw_line ()
gdk_draw_rectangle ()
gdk_draw_arc ()
gdk_draw_polygon ()
gdk_draw_string ()
gdk_draw_text ()
gdk_draw_pixmap ()
gdk_draw_bitmap ()
gdk_draw_image ()
gdk_draw_points ()
gdk_draw_segments ()

详见参考文档或头文件<gdk/gdk.h> 。这些函数的头两个参数都相同。第一个参数是可绘区域。第二个参数是图像关联 (GC)。

一 个图像关联封装一些信息,如前景色、背景色和线宽。GDK有一组函数用于创建和修改图像关联,但为了方便,我们仅使用预定义的图像关联。每个构件有一个相 关联的风格。(可以在 gtkrc 文件中修改,详见 GTK 的 rc 文件)其中,存储了许多图像关联。一些访问这些图像 关联的示例如下:

widget->style->white_gc
widget->style->black_gc
widget->style->fg_gc[GTK_STATE_NORMAL]
widget->style->bg_gc[GTK_WIDGET_STATE(widget)]

域值fg_gcbg_gcdark_gclight_gc 索引取值靠一个GtkStateType 类型的参数,该类型可以取如下值:

GTK_STATE_NORMAL,
GTK_STATE_ACTIVE,
GTK_STATE_PRELIGHT,
GTK_STATE_SELECTED,
GTK_STATE_INSENSITIVE

例如,GTK_STATE_SELECTED 默认的前景色是白色,默认的背景色是暗蓝色。

我们的函数draw_brush() 做实际的屏幕绘制工作。函数如下:

/* 在屏幕上绘制一个矩形 */
static void
draw_brush (GtkWidget *widget, gdouble x, gdouble y)
{
GdkRectangle update_rect;

update_rect.x = x - 5;
update_rect.y = y - 5;
update_rect.width = 10;
update_rect.height = 10;
gdk_draw_rectangle (pixmap,
widget->style->black_gc,
TRUE,
update_rect.x, update_rect.y,
update_rect.width, update_rect.height);
gtk_widget_draw (widget, &update_rect);
}

在位图上绘制了矩形之后,我们调用如下函数:

void       gtk_widget_draw                (GtkWidget           *widget,
GdkRectangle *area);

它会通知X参数area 给定的区域需要更新。 X 会最终会产生一个暴露事件(混合区域需要多次调用函数gtk_widget_draw() ),然后会调用暴露事件处理函数,复制相应的部分到屏幕上。

现在我们已经有了一个较完整的绘图程序,只差主窗口部分了。


<<< Previous Home Next >>>
事件处理Up 添加XInput支持
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值