第16章 GDK基础.docx

上传人:b****6 文档编号:8672911 上传时间:2023-02-01 格式:DOCX 页数:47 大小:403.73KB
下载 相关 举报
第16章 GDK基础.docx_第1页
第1页 / 共47页
第16章 GDK基础.docx_第2页
第2页 / 共47页
第16章 GDK基础.docx_第3页
第3页 / 共47页
第16章 GDK基础.docx_第4页
第4页 / 共47页
第16章 GDK基础.docx_第5页
第5页 / 共47页
点击查看更多>>
下载资源
资源描述

第16章 GDK基础.docx

《第16章 GDK基础.docx》由会员分享,可在线阅读,更多相关《第16章 GDK基础.docx(47页珍藏版)》请在冰豆网上搜索。

第16章 GDK基础.docx

第16章GDK基础

第16章GDK基础

16.1GDK和Xlib

GTK是用于实现图形用户接口的函数库。

在Linux平台上,GUI(图形用户接口)使用的是称为X窗口(XWindow)的系统。

X窗口系统是1984年由美国麻省理工学院(MIT)开发的。

在Linux上使用的X窗口系统是一种称为XFree86的X版本。

X窗口系统与MicrosoftWindows的图形用户接口有所不同,它是基于客户/服务器的。

X服务器在计算机上运行,控制监视器、鼠标和键盘。

X客户通过网络与服务器通讯。

X服务器为X客户提供图形显示服务。

也就是说,X客户和X服务器可能在同一台计算机上运行,也可能在不同的计算机上运行。

X窗口系统带有一套低级的库函数,称为Xlib。

Xlib提供了许多对X窗口的屏幕进行操作的函数。

当然,使用Xlib函数在屏幕上创建构件是很复杂的。

GTK要在屏幕上绘制各种构件,就需要与X服务器打交道。

但是GTK提供的构件库并未直接使用Xlib,而是使用了一个称为GDK的库。

GDK的意思是GIMPDrawingToolkit,亦即GIMP绘图工具包。

差不多每个Gdk函数都是一个相应Xlib函数的封装。

但是Xlib的某些复杂性(和功能)被隐藏起来了。

这样是为了简化编程,使Gdk更容易移植到其他窗口系统(有一个在Windows平台上的Gdk版本)。

被隐藏的Xlib功能一般是程序员极少用到的,例如,Xlib的许多特性只有窗口管理器才会用到,所以没有封装到Gdk当中。

如果需要,可以在应用程序中直接调用Xlib函数,只要在文件头部包含gdk/gdkx.h头文件就可以了。

一般情况下,如果要创建普通的图形接口应用程序,使用GTK就可以了。

Gtk+和Gnome构件库提供了极为丰富的构件,足以构造非常复杂的用户界面。

但是,如果需要开发新构件,或者要创建绘图程序,仅使用GTK就不够了。

这时可以采用Xlib,更好的方法是使用GDK库,它可以应付绝大多数的编程需要。

本章介绍了关于GDK的一些基本知识,这些也是创建构件和绘图的基础。

更多的GDK细节内容,请参考gdk.h头文件。

如果想了解Gdk函数的实现细节(比如它对应于Xlib的哪一个函数),可以看一下Gdk的源代码以确定它所封装的Xlib函数,然后用man指令参看该函数的手册页。

例如,下面是gdk_draw_point()函数的实现代码:

void

gdk_draw_point(GdkDrawable*drawable,

GdkGC*gc,

gintx,

ginty)

{

GdkWindowPrivate*drawable_private;

GdkGCPrivate*gc_private;

g_return_if_fail(drawable!

=NULL);

g_return_if_fail(gc!

=NULL);

drawable_private=(GdkWindowPrivate*)drawable;

if(drawable_private->destroyed)

return;

gc_private=(GdkGCPrivate*)gc;

XDrawPoint(drawable_private->xdisplay,drawable_private->xwindow,

gc_private->xgc,x,y);

}

每一个数据结构都被转换给它的一个“私有”版本,该“私有”版本包含了与GDK正在使用的特定窗口系统的相关信息,这样可以将与特定窗口系统相关的函数声明排除在gdk/gdk.h头文件外。

每个数据结构的“私有”版本都包含一个封装的Xlib数据结构,且这个数据结构被传递到XDrawPoint()函数中,所以XDrawPoint()函数的文档也适用于gdk_draw_point()函数。

16.2GdkWindow

GdkWindow是Xlib窗口对象的封装。

一个GdkWindow代表屏幕上的一个区域,可以显示或隐藏起来(在Xlib里面称为映射或反映射窗口),也可以捕获GdkWindow接收到的事件,还可以在里面绘制图像,移动或调整图像的尺寸。

GdkWindow是以树状结构组织的,也就是说,每一个窗口都可以有子窗口。

子窗口是相对于父窗口的位置定位的,当父窗口移动时,子窗口也会移动。

子窗口不会在父窗口边界外的区域绘出(也就是说,它们会被父窗口剪裁)。

所谓GdkWindow窗口的树状组织并不是针对每个应用程序的,实际上有一个由X服务器和窗口管理器控制的窗口的全局树。

根窗口没有父窗口,所有窗口都是从它派生而来的。

作为桌面背景,根窗口的全部或部分总是可见的。

每个窗口都可以为不同的Linux进程所拥有,一些窗口是由窗口管理器所创建的,还有一些来自于用户的应用程序。

GdkWindow和GtkWindow是完全不同的东西。

GtkWindow是一个Gtk+构件,用于表示顶级(toplevel)窗口(顶级窗口是在窗口层次中由应用程序控制的最高级别的窗口)。

典型情况下,窗口管理器为顶级窗口创建各种装饰,包括标题条、关闭按钮以及窗口外观等。

要理解X窗口首先要知道它是X服务器上的一个对象,这一点很重要。

X客户对每一个窗口获得一个独一无二的整数ID号,并用ID号码引用该窗口。

这样,所有的窗口操作都发生在服务器上,并且所有与X窗口打交道的函数都要通过网络传输。

GdkWindow是由X返回的整数ID号的一个封装。

它确实保存一些信息的本地拷贝(比如说窗口的尺寸),所以一些Gdk操作比相应的Xlib操作效率更高。

还有,GdkWindow本质上是服务器端对象的一个句柄。

许多Gdk对象都是相似的,字体、像素映射图片、鼠标光标等等也是服务器端对象的句柄。

16.2.1GdkWindow和GtkWidget

许多GtkWidget子类都有一个相关联的GdkWindow窗口。

理论上,Gtk+应用程序可以只创建一个顶级窗口,并将所有构件画在里面。

然而,这么做并没有什么实际意义,因为GdkWindow允许X窗口系统自动处理许多细节。

例如,Gdk所接收到的事件都使用它们所发生的窗口标志,这使得Gtk+能很快确定每个事件是哪个构件发生的。

有一些构件是没有与之相关联的GdkWindow窗口的,它们称为“无窗口”的构件,用一个GTK_NO_WINDOW标记来标志它们(可以用GTK_WIDGET_NO_WINDOW()宏来测试它们)。

没有窗口的构件会将自身绘制在其父构件容器的GdkWindow窗口上。

无窗口构件相对较小,占用资源较少,一般将它们称为“轻量级”的,GtkLabel构件就是一个最常见的例子。

因为事件总是由GdkWindow窗口接收的,无窗口构件不能接收事件。

如果想让无窗口构件捕获事件,可以使用GtkEventBox容器构件。

16.2.2GdkWindow属性

创建GdkWindow时,gdk_window_new()函数允许指定窗口的所有属性,这些属性以后也可以再改变。

要指定多个属性,可以向函数传递一个GdkWindowAttr对象。

GdkWindowAttr对象的内容就是GdkWindow窗口的属性。

下面是GdkWindowAttr结构的定义:

typedefstruct_GdkWindowAttrGdkWindowAttr;

struct_GdkWindowAttr

{

gchar*title;

gintevent_mask;

gint16x,y;

gint16width;

gint16height;

GdkWindowClasswclass;

GdkVisual*visual;

GdkColormap*colormap;

GdkWindowTypewindow_type;

GdkCursor*cursor;

gchar*wmclass_name;

gchar*wmclass_class;

gbooleanoverride_redirect;

};

因为GdkWindowAttr结构的一些成员是可选的,所以gdk_window_new()函数用一个attributes_mask参数指定哪一个可选成员里包含有效的数据。

Gdk只检查在屏蔽值里面指定的成员,这样可以让不感兴趣的成员保留缺省值。

下面的函数列表简要概括了这些值。

没有attributes_mask标志的成员必须指定,因为它们没有缺省值。

gdk_window_new()函数最典型的是用在构件的实现中,用来创建构件的GdkWindow。

在其他场合下极少用到它。

gdk_window_destroy()函数销毁GdkWindow窗口。

函数列表:

GdkWindow

#include

GdkWindow*gdk_window_new(GdkWindow*parent,

GdkWindowAttr*attributes,

gintattributes_mask)

voidgdk_window_destroy(GdkWindow*window)

下面简要介绍GdkWindowAttr结构中各个成员的意义。

第一个成员title是GdkWindow的标题,它只对顶级窗口才有实际意义,大多数窗口管理器把它放在标题条上。

通常,不要在创建GdkWindow窗口时指定title值,应该让用户调用gtk_window_set_title()函数来指定它。

第二个成员event_mask是窗口的事件屏蔽,它决定这个窗口接收什么事件。

后面会有详细的介绍。

第三个和第四个成员x、y是窗口的X、Y坐标,它们是以像素度量的;这两个坐标是相对于父窗口原点的坐标。

每个窗口的原点都是它的左上角(西北角)。

注意,它们是16位的有符号整数。

X窗口最大可以是32768像素,它可以是负数值,不过会被它的父窗口剪裁掉(只有在父窗口内部的区域才是可见的)。

第五个和第六个成员width、height是窗口的宽度和高度,它们是以像素度量的,也是16位的有符号整数。

第七个成员GdkWindowClass可取以下两种值:

•GDK_INPUT_OUTPUT:

GdkWindow是一个普通窗口

•GDK_INPUT_ONLY:

GdkWindow是一个窗口,它有一个位置,能接收事件,但没有视觉上的表示,也就是说它是不可见的。

它的子窗口也必须是这种类型的。

你可以为这种窗口设置光标和其他的属性,但是没有办法把窗口画出来(因为它是不可见的)。

这种窗口有时候用于捕获事件或改变两个普通窗口重叠区域的鼠标光标。

第八个成员visual(视件)描述了一个显示器的颜色处理特征;第九个成员colormap(颜色表)包含了用于绘画的颜色。

第十个成员window_type指定GdkWindow的类型。

窗口可以是下面几种不同类型之一,由GdkWindowType枚举类型指定:

•GDK_WINDOW_ROOT:

是根窗口的Gdk封装类型,在初始化时创建。

•GDK_WINDOW_TOPLEVEL:

是一个顶级窗口。

在这种情况下,gdk_window_new()函数的parent参数应该设为NULL。

Gdk自动使用根窗口作为它的父窗口。

•GDK_WINDOW_CHILD:

是一个在顶级窗口中的下级窗口。

•GDK_WINDOW_DIALOG:

基本上与顶级窗口是一样的。

它的父窗口应该是NULL,并且Gdk会替换根窗口。

应该设置一个窗口类提示(wmclass_name)告诉窗口管理器这个窗口是一个对话框,一些窗口管理器会考虑这些情况并作适当的处理。

•GDK_WINDOW_TEMP:

用于弹出菜单或其他类似的东西。

它是一个只需暂时存在的窗口。

它是一个顶级窗口,所以它的父窗口应该是NULL。

这种窗口的鼠标光标总是与它们父窗口的一样。

所以它们会忽略属性结构中的相关成员值。

•GDK_WINDOW_PIXMAP:

根本就不是窗口。

在Gdk中GdkPixmap和GdkWindow差不多是同样处理的,所以Gdk用同样的结构表示它们;它们可以视为GdkDrawable类型。

•GDK_WINDOW_FOREIGN:

标识一个不是由Gdk创建的窗口的封装。

对gdk_window_new()来说,只有GDK_WINDOW_TOPLEVEL、GDK_WINDOW_CHILD、GDK_WINDOW_TEMP和GDK_WINDOW_DIALOG是有效的。

库用户不会创建一个GDK_WINDOW_ROOT。

pixmap(GDK_WINDOW_PIXMAP)是用gdk_pixmap_new()创建的。

外来窗口(GDK_WINDOW_FOREIGN)是在Gdk外部创建并用gdk_window_foreign_new()封装的X窗口。

第十一个成员cursor指定在这个窗口中的鼠标的指针(光标)形状。

第十二个成员wmclass_name前面已经介绍过了。

写构件时,通常不设置类提示,它只与顶级窗口有关。

Gtk+提供了gtk_window_set_wmclass()函数,程序员可以将它设置为具有确切含义的值。

GdkWindowAttr的最后一个成员override_redirect决定窗口是否“替换重定向”的。

通常,窗口管理器截获所有对顶级窗口的显示、隐藏、移动或尺寸调整请求。

你可以重定向或取消这些请求,让顶级窗口按窗口管理器的布局策略行事。

将override_redirect设置为TRUE,禁止窗口管理器对窗口的管理。

因为窗口管理器不能移动设置了这个标志的窗口,通常也不会为这样的窗口设置标题条或其他的装饰。

注意,所有的GDK_WINDOW_TEMP窗口都将这个成员设为TRUE;GDK_WINDOW_TEMP通常用作弹出菜单,窗口管理器不能控制它。

一般不应该改变override_redirect成员。

如果指定了正确的GdkWindowqType,缺省值差不多总是正确的。

不过还是有一些例外,例如Gnome面板应用程序设置了这个成员。

16.3视件和颜色表

硬件之间总存在差别。

最原始的X服务器只支持两种颜色,每一个像素只能是on或off(开或关)。

这就是“每像素一位”(bpp)显示模式。

每像素一位的显示模式称为深度为1。

多数高级的X服务器支持每像素24或32位,还允许以窗口为基础指定不同的深度。

每像素24位允许224(16777216)种像素,包含了比人眼能分辨的还要多的颜色。

从概念上说,位图显示由一个矩形的像素网格组成。

每个像素由一些固定的位数组成;像素以一种硬件相关的方法映射为可视的颜色。

考虑这种概念的一种方法就是想象一个二维的整数数组,整数的大小等于要求的位数。

换一种说法,可以想象一种显示就像一个“位平面”栈,或“位”的二维数组。

如果每个平面都平行于其他平面,那么一个像素就是一根在相同坐标处穿过每个平面的垂线,并且从每一个平面处获得一位。

这就是术语“深度”的起源,因为每个像素的位数等于位平面栈的深度。

在X窗口系统中,像素代表在一个颜色查找表中的入口。

一种颜色就是一组红、绿、蓝(RGB)值—监视器以一定比率混合红绿蓝光以显示每个像素。

例如,考虑一种八位的显示模式:

八位不足以为现实中的颜色编码,只可能为很少部分的RGB值编码。

作为替代,数据位被解释为整数,用于为RGB颜色值做索引。

这个颜色表称为colormap(颜色表),有时,你也可以修改它以包含要使用的颜色,虽然这样做是硬件相关的(一些colormap是只读的)。

视件(visual)用来决定像素的位模式如何转换为一个可见的颜色。

因而,视件还定义了颜色表如何工作。

在八位显示中,X服务器也许将每个像素解释为一个包含256种可能颜色值的颜色表的索引。

典型情况下,24位视件有三个颜色表:

一个是红色的浓淡值,一个是绿色的浓淡值,一个是蓝色的浓淡值。

每个颜色表用一个八位的值索引;三个八位值组成24位的像素。

视件定义了像素内容的含义,还定义了颜色表是只读的还是可修改的。

简而言之,视件就是特定X服务器的颜色容量的描述。

在Xlib中,你得围绕视件做很多罗嗦的事,但是Gdk和Gtk+能极大地简化了这些繁琐工作。

16.3.1GdkVisual

Xlib能报告一个所有可用的视件以及相关信息的列表;Gdk在一个称为GdkVisual的结构中保持一个这些信息的客户端拷贝。

Gdk能报告可用的视件,并将它们以不同的方式分级。

在多数时候,只需用gdk_visual_get_system()函数就可以了,它返回一个指向缺省视件的指针。

如果正在写一个GtkWidget构件,gtk_widget_get_visual()函数将返回应该使用的视件。

返回的视件不是一个拷贝,所以不需要释放它,Gdk将永久保存视件。

获取缺省视件

#include

GdkVisual*gdk_visual_get_system()

下面是GdkVisual结构的定义,大多数成员都用于由颜色计算像素值。

typedefstruct_GdkVisualGdkVisual;

struct_GdkVisual

{

GdkVisualTypetype;

gintdepth;

GdkByteOrderbyte_order;

gintcolormap_size;

gintbits_per_rgb;

guint32red_mask;

gintred_shift;

gintred_prec;

guint32green_mask;

gintgreen_shift;

gintgreen_prec;

guint32blue_mask;

gintblue_shift;

gintblue_prec;

};

16.3.2视件的类型

视件用不同的度量方法加以区分。

它们可以是灰度级或者RGB值,颜色表可以是可修改的或者固定的,像素值可以是单个的颜色表或者包含了压缩的红、绿、蓝的索引值。

下面是GdkVisualType的可能取值:

•GDK_VISUAL_STATIC_GRAY:

意味着显示器是单色的或者灰度的,颜色表不能修改。

一个像素值只是一个灰度级别,每个像素都是“硬编码”,分别代表一个确定的屏幕上的颜色。

•GDK_VISUAL_GRAYSCALE:

意味着显示器是可修改的,但是只有灰度的级别才可能修改。

像素代表在颜色表中的一个入口,所以给定的像素在不同的时候能够代表不同的灰度级别。

•GDK_VISUAL_STATIC_COLOR:

代表一种颜色显示,它使用单个只读的颜色表而不是红、绿、蓝每种颜色各一个单独的颜色表。

这种显示差不多就是12位或更少(使用单个颜色表的24位显示器需要一个带224个入口的颜色表,差不多有500MB)。

这是一种恼人的视件,因为它的可用颜色太少,而且不能改变成它们的实际颜色。

•GDK_VISUAL_PSEUDO_COLOR:

从很多年前开始,就一直是低端PC硬件的常用视件。

如果有一个1MB显存、256色的显示卡,这极有可能就是你的X服务器的视件。

它代表一种具有读/写颜色表的颜色显示。

像素只对单个颜色表索引。

•GDK_VISUAL_TRUE_COLOR:

是带三个只读颜色表的颜色显示,红、绿、蓝每种颜色有一个颜色表。

一个像素包含三个索引,每个颜色表一个。

在像素值和RGB三元组之间有固定的数学关系,可以用下面的公式从[0,255]间的红、绿、蓝值获取像素值:

gulongpixel=(gulong)(red*65536+green*256+blue)。

•GDK_VISUAL_DIRECT_COLOR:

是一种有三个读写颜色表的颜色显示。

如果使用Gdk颜色处理例程,它们只是简单地填充所有三个颜色表以模拟真彩显示。

16.3.3颜色和GdkColormap

GDK使用GdkColor存储RGB值和像素值。

红、绿、蓝值是以16位无符号整数给出的,取值范围为0到65535。

像素的内容依赖于视件。

下面是GdkColor结构定义:

typedefstruct_GdkColorGdkColor;

struct_GdkColor

{

gulongpixel;

gusho

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1