gtk函数

合集下载

Linux下的GTK图形界面编程

Linux下的GTK图形界面编程

注意fill取FALSE值,expand取TRUE值时与expand取FALSE值,fill值无效的区别。前者的盒子仍是原来创建盒子时指定的大小,而后者的盒子已经缩小到打包组件的大小了。
gtk_box_pack_end()函数的参数与上面描述的一致。只是排列顺序分别是从下到上
,从右到左。
gtk_widget_show (window); /*显示窗口*/
gtk_main (); /*进入睡眠状态,等待事件激活*/
return(0);
}
从上面的程序可以看出,GTK是一个事件驱动工具包,当它运行到gtk_main()函数时会自动睡眠,直到有事件发生,控制权转让给相应的函数调用,在该函数中可以用标准C写出相应的事物逻辑。这与windows 上的程序处理是一样的。
该函数的第二个参数就是上述gtk_signal_connect()函数的返回值,即关联标签。第一个参数指向了去除关联的对象名称。这样可以做到断开事件与回调函数的关联,使得事件发生后,不会调用相关的回调函数。
布局格式
2.1打包盒子
对GTK显示格式的控制是通常通过打包盒子来完成的。widget组件打包可以采用两种方式,水平盒子和垂直盒子。若将widget组件打包进平行盒子,组件就被依次水平的插入窗口;若是垂直盒子,则组件排列是垂直的。产生新的水平盒子的函数为
目前已经开发出来GTK的增强版GTK+。GTK+是将GTK,GDK,GLIB集成在一起的开发包,可以工作在许多类似于UNIX的系统上,没有GTK的平台限制。
1.GTK的消息处理机制
下面我们先看一个基本的例子,该例子产生一个200×200像素的窗口。它不能自己退出,只能通过shell来杀死进程(调用kill命令)。

2024年傅老师GTK简易教程

2024年傅老师GTK简易教程
傅老師GTK簡易教程
2024/2/29
1
目录
• GTK基础概念 • GTK环境搭建 • GTK界面设计 • GTK图形绘制 • GTK数据存储与处理 • GTK高级特性
2024/2/29
2
01
GTK基础概念
2024/2/29
3
GTK定义及作用
2024/2/29
GTK(GIMP Toolkit)是一个 开源的、跨平台的、用于创建
06
在macOS系统中,可以使用Homebrew等包管理器安装 GTK+开发环境。
8
第一个GTK程序
• 创建一个C语言源文件,例如hello.c,并 输入以下代码
2024/2/29
9
第一个GTK程序
```c
include <gtk/gtk.h>
2024/2/29
int main(int argc, char *argv[]) {
10
第一个GTK程序
GtkWidget *window;
gtk_init(&argc, &argv);
2024/2/29
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
11
第一个GTK程序
• gtk_widget_show(window);
2024/2/29
支持本地化资源文件,如翻译后的字符串、图 片等,方便开发者进行本地化开发。
2024/2/29
双向文本支持
支持双向文本排版,满足阿拉伯语、希伯来语等从右到左书写语言的需求。
34
THANKS
感谢观看
2024/2/29
35

GTK+ 2.0 教程

GTK+ 2.0 教程

GTK+ 2.0 教程版本号:V_0.1.0 2002年6月25日本文是有关通过 C 语言接口使用GTK (the GIMP Toolkit) 的教程。

Table of Contents中文版说明简介 (4)从这里开始 (4)用 GTK 来写 Hello World编译 Hello World 程序信号和回调函数的原理事件Hello World 详解继续 (12)数据类型深入探索信号处理函数改进了的 Hello World组装构件 (14)组装盒的原理盒的细节组装示范程序用表组装表组装示例构件概述 (23)类型转换构件的组织无窗口构件按钮构件 (26)一般按钮 Normal Buttons开关按钮 Toggle Buttons复选按钮 Check Buttons单选按钮 Radio Buttons调整对象Adjustments ………………………………………………………………………………………………………………31创建一个调整对象轻松使用调整对象“调整对象”的内部机制范围构件Range Widgets ……………………………………………………………………………………………………………33滚动条构件 Scrollbar Widgets比例构件 Scale Widgets创建一个比例构件函数和信号 ( 至少讲了函数 )常用的范围函数设置更新方式获得和设置调整对象键盘和鼠标绑定示例杂项构件 (39)标签 Labels1箭头 Arrows工具提示对象 The Tooltips Objec t进度条 Progress Bars对话框 Dialogs标尺 Rulers状态栏 Statusbars文本输入构件 Text Entries微调按钮 Spin Buttons组合框 Combo Box日历 Calenda r颜色选择 Color Selection文件选择 File Selections容器构件Container Widgets ………………………………………………………………………………………………………76事件盒 The EventBox对齐构件 The Alignment widge t固定容器 Fixed Containe r布局容器 Layout Containe r框架 Frames比例框架 Aspect Frames分栏窗口构件 Paned Window Widgets视角 Viewports滚动窗口 Scrolled Windows按钮盒 Button Boxes工具栏 Toolba r笔记本 Notebooks菜单构件 (100)手工创建菜单手工菜单示例使用套件套件示例无文档构件 (106)快捷标签 Accel Labe l选项菜单 Option Menu菜单项 Menu Items复选菜单项 Check Menu Item单选菜单项 Radio Menu Item分隔菜单项 Separator Menu Item分离菜单项 Tearoff Menu Item曲线图 Curves绘图区 Drawing Area字体选择对话框 Font Selection Dialog消息对话框 Message DialogGamma 曲线图图像 Image插头和插座 Plugs and Sockets树视区 Tree View文本视区 Text View设置构件的属性超时、IO 和Idle 函数 (108)超时 Timeouts监控 IOIdle 函数高级事件和信号处理信号函数连接和断开信号处理函数2阻塞和反阻塞信号处理函数发出和停止信号信号的发射和传播操作选中区概述获取选中区信息提供选中区拖放概述属性函数设置源构件源构件上的信号设置目的构件目的构件上的信号GLib定义双向链表单向链表存储管理计时器字符串处理实用程序和错误处理函数GTK 的 rc 文件rc 文件的功能GTK rc 文件的格式rc 文件示例编写你自己的构件 (124)概述一个构件的剖析创建一个复合构件介绍选择一个父类头文件get_type() 函数class_init() 函数init() 函数其余的 .. .从头创建构件介绍在屏幕上显示构件表盘构件的原形主体gtk_dial_realize()大小磋商gtk_dial_expose()事件处理可能的增强深入的学习涂鸦板,一个简单的绘图程序 (141)概述事件处理绘图区构件和绘图添加 XInpu t 支持允许扩展设备信息使用扩展设备信息得到更多关于设备的信息进一步的讲解编写GTK 应用程序的技巧 (151)3简介GTK (GIMP Toolkit) 是一套用于创建图形用户界面的工具包。

gtk编程——菜单

gtk编程——菜单

一、建立菜单菜单由菜单条(GtkMenuBar)和从菜单条或其他菜单下拉的菜单(GtkMenu)组成。

在建立菜单条以前必须先建立应用程序的纵向组合框。

建立菜单分为下面几个步骤:(1)建立菜单条(GtkMenuBar),并把它加到纵向组合框内。

函数gtk_menu_bar_new建立GtkMenuBar构件。

1.下面是建立菜单和将它放入纵向组合框的代码:menuber=gtk_menu_bar_new();gtk_box_pack_start(GTK_BOX(vbox),menubar,FALSE,TRUE,0);gtk_widget_show(menubar);(2)建立后的菜单条是空的,还需要增加菜单项。

用gtk_menu_item_new_with_label建立带标号的菜单项。

如:建立标号为“File”的菜单项用下面的语句:meanFile=gtk_menu_item_new_item_new_with_label(“File”);2.(3)在建立菜单项后,需要将它加到前面建立的菜单条中。

gtk_menu_bar_append函数能够实现上面的功能。

我们把上面的菜单项加到菜单条里面的代码如下:gtk_menu_bar_append(GTK_MENU_BAR(menubar),MenuFile);注意gtk_menu_bar_append和下面的gtk_menu_bar_append实际上都是宏,gtk_menu_bar_append的定义是这样如下:下面我们给出gtk_nenu_shell_append函数的原型:3、于是上面的代码也可以改成:gtk_menu_shell_append(GTK_MENU_SHELL(menubar),MenuFile);到这里我们就可以编写如下图的菜单了到这里我们已经建立了一个简单的菜单条,但大多数菜单每个菜单向都包括一个子菜单。

这席菜单只有在下拉菜单时才能看到。

Gtk函数

Gtk函数

1.Gtk_init(&argc,&argv):这个函数 gtk_init(gint *argc, gchar ***argv) 会在每个 GTK 应用程序中调用。

该函数设定了默认的视频(visual)和颜色映射模式(color map),接着会调用函数 gdk_init(gint *argc, gchar ***argv)。

该函数初始化要使用的库,设定默认的信号处理,并检查传递给你的程序的命令行参数,寻找下列之一:∙--gtk-module∙--g-fatal-warnings∙--gtk-debug∙--gtk-no-debug∙--gdk-debug∙--gdk-no-debug∙--display∙--sync∙--name∙--class2.gtk_window_new (GTK_WINDOW_TOPLEVEL):GTK_WINDOW_TOPLEVEL 参数指我们要使用窗口管理器来修饰和放置窗口。

这里不会创建一个 0x0 大小的窗口,一个没有子构件的窗口默认大小设置为 200x200,这样你仍然能操作它。

3.gtk_widget_show() :函数让 GTK 知道,我们已经设置完构件的属性,可以显示它了。

4.gtk_main():是另一个可以在每个 GTK 程序中见到的函数调用。

当程序运行到这里,GTK 会“睡着”等待 X 事件 (如按钮或键盘按下)、超时(timeouts)或文件 IO 通知发生。

5.GTK连接时常用的库:GTK 库(-lgtk),构件库,基于 GDK。

GDK 库(-lgdk),Xlib 库的封装(wrapper)。

gdk-pixbuf 库(-lgdk_pixbuf),图像处理库。

Pango 库(-lpango),处理国际化文本。

gobject 库(-lgobject),包含作为GTK 基础的类型系统。

gmodule 库(-lgmodule),动态运行库。

gtk编程——概述

gtk编程——概述

一、什么是GNOME、GNOME的意思是“GNU Network Object Model Environment”(GNU网络对象模型环境),是Linux世界令人激动的软件开发成果。

虽然它的名字比较长,但这个软件项目的目的却很简单,那就是实现一个永恒友好的、功能强大的用户和开发桌面环境,而这一环境又完全是以免费的开源代码软件为基础的。

正像它名字的那样,GNOME既是一个桌面,也是一个完整的程序设计环境。

GNOME是底层X窗口系统和高层管理器软件中间的一个程序设计界面,它向GUI程序员提供了丰富的功能和强大的开发工具,这些工具是传统意义上的Linux所缺乏的。

二、什么是GIMP、GTK+GNOME中的基本工具包是GTK+(即GIMP工具包),它最初是为了简化GIMP的开发工作而编写出来的。

GIMP是UNIX类操作系统上的影像处理程序。

GIMP是通用影像处理程序或者GNU影像处理程序的缩写。

它的功能类似Windows的Photoshop。

GTK+是一个性能优异的、面向对象的、跨平台的、不依赖于具体语言的开发工具包,在GNOME出现之前就已经大量地用来开发各种软件程序了。

GTK+能够支持许多程序设计语言,其中包括C、C++、TOM、PERL、Python、GUILE、ADA等。

三、GTK+使用的库GTK+使用GLIB库和GDK(GIMP Drawing Kit,GIMP绘图工具包)系列的开发库,GLIB定义了数据类型,提供了错误处理和内存管理方面的函数;而GDK则是本地图形化API和GTK+ 中间的一个过渡层,它需要依赖具体的计算机平台。

因此,向其他计算机平台上移植GTK+ 只需要重新编写GDK。

四、GTK+的安装一般来说最新的Redhat完全安装就带GTK+工具库了。

大家直接可以在上面开发程序。

如果当前系统没有GTK+工具库,可以到.下载源码安装。

具体安装方法可以。

参见CU上的GTK+ 2.0安装的帖子,这里不再叙述。

gtk编程 - 窗体

gtk编程 - 窗体

gtk编程 - 窗体一、初始化GTK+写GTK+程序需要调用gtk_init函数对GTK+ 库函数进行初始化。

1.名称::功能:头文件:函数原形:参数:返回值: gtk_init 初始化GTK+库 #include voidgtk_init(int *argc,char ***argv); argc 指向主函数argc的指针 argv 指向主函数argv的指针无在你程序使用到GTK+工具库之前,必须对它进行初始化。

gtk_init可以初始化GTK+工具库。

gtk_init的参数的指向主函数argc,argv的指针,它可以改变一些不满足GTK+函数要求的命令行参数。

因为gtk_init函数没有返回值,所以如果在初始化过程中发生错误程序就会立即退出。

2.名称::功能:头文件:函数原形:参数:返回值: gtk_init_check初始化GTK+库 #include gboolean gtk_init_check(int *argc,char ***argv); argc 指向主函数argc的指针 argv 指向主函数argv的指针成功返回TURE,出错返回FALSE。

还有一个GTK+库初始化函数gtk_init_check,它的作用和gtk_init完全相同。

唯一的区别是gtk_init_check有返回值,可以判断初始化是否成功。

二、建立窗口 GTK+的构件是GUI的组成部分。

窗口、检查框、按钮和编辑字段都属于构件。

通常将构件和窗口定义为指向GtkWidget结构的指针。

在GTK+中,GtkWidget是用于所有构件和窗口的通用数据类型。

GTK+ 库进行初始化后,大多数应用建立一个主窗口。

在GTK+中,主窗口常常被称为顶层窗口。

顶层窗口不被包含在任何其他窗口内,所以它没有上层窗口。

在GTK+ 中,构件具有父子关系,其中父构件是容器,而子构件则是包含在容器中的构件。

顶层窗口没有父窗口,但可能成为其他构件的容器。

gtk空格键的信号函数

gtk空格键的信号函数

gtk空格键的信号函数English Answer:The spacebar may not be the most exciting key on your keyboard, but it gets a lot of use. From typing to gaming, the spacebar helps you do more. Because the spacebar is used so frequently, GTK+ provides a number of ways to handle spacebar events.`GtkWidget::KeyPressEvent`。

`GtkWidget::ButtonPressEvent`。

`GtkWidget::ButtonReleaseEvent`。

`Gtk::events()`。

GtkWidget::KeyPressEvent.A `KeyPressEvent` is generated when a key is pressed.This event contains information about the key that was pressed and the modifiers that were active at the time. You can use `KeyPressEvent` to handle spacebar presses by checking the value of the `keyval` member. If the `keyval` member is `GDK_KEY_space`, then the spacebar was pressed.cpp.bool on_key_press_event(GtkWidget widget, GdkEventKey event) {。

if (event->keyval == GDK_KEY_space) {。

GTK:如何让你的程序正常退出?

GTK:如何让你的程序正常退出?

GTK:如何让你的程序正常退出?前面创建的窗口只能关闭,但是不能让程序正常退出,那么如何让你的程序正常退出呢?首先,我们需要能使用用程序结束的函数:结束应用程序1.gtk_main_quit函数可以结束程序若想要应用程序能够正常退出,仅仅有能使程序的函数是不够的,我们还需要了解几个概念:事件、信号、回调函数。

事件:用户对程序的操作,比如按一下鼠标、拖动窗口、按下窗口的按键等等。

信号:事件发生时,相应的构件将给应用程序的回呼函数提供信号回调函数:当需要对信号进行处理时,需要用GTK+登记回调函数,并将它和构件联系在一起。

构件可以登记回调函数,回调函数可与多个构件联系在一起。

GTK常用的回调函数有下面两个:2.g_signal_connect用于登记一个GTK+信号,其功能有点像普通信号登记函数signal.当某个空间发出信号,程序就会去执行由g_signal_connect登记的回调函数。

3.g_signal_connect_swapped() 的作用和g_signal_connect() 相同,只是回调函数只用一个参数,一个指向 GTK 对象的指针。

所以当使用这个函数连接信号时,回调函数应该是这样的形式void callback_func( GtkObject *object );这个对象常是一个构件。

然而我们通常不用函数g_signal_connect_swapped() 设置连接。

它们常被用在只接受一个单独的构件或者对象的回调函数中作为参数,如同我们的 helloworld 示例中那样。

拥有两个设置信号连接函数的目的是简单的允许回调函数有不同数目的参数。

GTK 库中许多函数仅接受一个单独的构件指针作为其参数,所以对于这些函数你要用g_signal_connect_swapped(),然而对你自己定义的函数,你需要附加的数据提供给你的回调函数。

GTK:HelloWorld详解

GTK:HelloWorld详解

GTK:HelloWorld详解现在我们知道基本理论了,让我们来详细分析helloworld示例程序。

这是按钮被点击时要调用的回调函数。

在这个示例中我们忽略了参数widget 和data,但是使用这些参数也不难。

下一个示例会使用data 参数来告诉我们哪个按钮被按下了。

void hello( GtkWidget *widget,gpointer data ){g_print ("Hello World\n");}接下来的一个回调函数有点特殊。

"delete_event" 在窗口管理器发送这个事件给应用程序时发生。

我们在这里可以选择对这些事件做什么。

可以忽略它们,可以做一点响应,或是简单地退出程序。

这个回调函数返回的值让GTK 知道该如何去做。

返回TRUE,让它知道我们不想让"destroy" 信号被发出,保持程序继续运行。

返回FALSE,我们让 "destroy" 信号发出,这接着会调用 "destroy" 信号处理函数。

gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data ){g_print ("delete event occurred\n");return TRUE;}这里是另一个回调函数,它通过调用gtk_main_quit() 来退出程序。

这个函数告诉 GTK 当控制权返回给它时就从 gtk_main 退出。

void destroy( GtkWidget *widget,gpointer data ){gtk_main_quit ();}我假设你知道 main() 函数...是的,像其它程序一样,所有的 GTK 程序有一个 main() 函数。

int main( int argc,char *argv[] ){接下来声明两个指向 GtkWidget 类型的结构的指针。

GDK

GDK

第16章GDK 基础16.1 GDK和XlibG T K是用于实现图形用户接口的函数库。

在L i n u x平台上,G U I(图形用户接口)使用的是称为X 窗口(X Wi n d o w)的系统。

X窗口系统是1 984年由美国麻省理工学院(M I T)开发的。

在L i n u x上使用的X窗口系统是一种称为X F r e e86的X版本。

X窗口系统与M i c r o s o f t Wi n d o w s的图形用户接口有所不同,它是基于客户/服务器的。

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

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

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

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

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

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

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

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

但是G T K提供的构件库并未直接使用X l i b,而是使用了一个称为G D K的库。

G D K的意思是GIMP Drawing To o l k i t,亦即G I M P绘图工具包。

差不多每个G d k函数都是一个相应X l i b函数的封装。

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

这样是为了简化编程,使G d k更容易移植到其他窗口系统(有一个在Wi n d o w s平台上的G d k版本)。

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

如果需要,可以在应用程序中直接调用X l i b函数,只要在文件头部包含g d k/g d k x.h头文件就可以了。

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

G t k+和G n o m e 构件库提供了极为丰富的构件,足以构造非常复杂的用户界面。

QT和GTK+

QT和GTK+

GTK+图形界面编程本章将介绍Linux下的图形界面编程,重点介绍基于C语言的具有面向对象特征的GTK+图形界面编程。

主要介绍GTK+图形界面应用程序的框架、基本原理、常用控件的使用。

本章重点:GTK+程序的基本结构。

事件和消息处理。

常用控件的使用。

本章难点:理解GTK+应用程序的基本原理。

熟悉常用控件的基本用法。

12.1 Linux下的图形界面编程12.1.1 Qt和GTK+虽然Linux下的大多数开发是基于字符界面的,但在Linux环境下也可以开发出美观大方的图形界面。

经过多年的发展,目前已经存在多种用于在Linux下开发图形界面程序的开发包,其中较为常用的是Qt和GTK+。

Qt是一个跨平台的图形用户界面开发库,它不仅支持Linux操作系统,还支持所有类型的UNIX以及Windows操作系统。

Qt良好的封装机制使它模块化程度非常高,可重用性很强,Qt提供了丰富的API供开发人员使用。

使用Qt开发的图形用户界面程序具有良好的稳定性和健壮性。

桌面环境KDE(K Desktop EnVironment即K桌面环境)就是使用Qt作为其底层库开发出来的。

由于Qt使用C++面向对象编程语言作为其开发语言,而许多在Linux下从事开发的程序员更喜欢或更习惯于用C语言。

GTK+使用C语言作为开发语言。

它基于LGPL授权,因此GTK+是开放源代码而且完全免费的。

GTK+简单易用,执行效率高。

基于这些原因,GTK+拥有为数众多的拥护者。

Linux的桌面环境GNOME就是建立在GTK+基础上。

GTK+简介简单地说,GTK+就是用C语言编写的用于开发图形界面程序的函数库。

GTK+来源于GIMP(GNU Image Minipulation Program 即GNU图像处理程序)。

GTK+在GDK(GIMP程序说明。

各参数说明如下。

object:指向产生消息的控件。

name:消息或事件的名称。

callback_func:事件发生后要执行的回调函数。

gtk库函常用数收录

gtk库函常用数收录

gtk库函常用数收录首先我们要把在回调函数on_expose_event() 中画出时间的数值。

这个回调函数与信号进行了绑定expose-event 。

如果这个信号发射出去了,这个窗口就会按照我们程序所.调用 gdk_cairo_create () 函数可为所绘制的图形创建一个 Cairo 环境。

cairo_fill () 函数将已经准备好的图案填充到矩形路径所构成的封闭区域中。

函数time_handler() 就会被按照我们在函数中的设置在设定的时间内不断的运行。

tk_text_new:创建文本构件,其参数允许为文本构件指定水平和垂直的调整对象,...gtk_text_freeze用来将构件“冻结”,停止其自动重绘,此时GtkText构件内显示的1.1 创建、配置文本构件gtk_text_new:创建文本构件,其参数允许为文本构件指定水平和垂直的调整对象,并且可以用于跟踪构件的位置。

向gtk_text_new 函数传递NULL,函数会为文本构件创建自己的调整对象。

gtk_text_set_adjustments可以用来指定其水平和垂直的调整对象当文本构件中的文本超过构件能显示的范围时,文本构件不会自动显示滚动条。

所以我们必须另行创建滚动条vscrollbar = gtk_vscrollbar_new(GTK_TEXT(text)->vadj)gtk_text_set_editable可用来设置构件是否可编辑文本构件在文本如果太长,一行显示不下时会换行。

缺省方式是换行后会将单词分成两半。

可以用以下函数gtk_text_set_word_wrap 来改变1.2 文本编辑gtk_text_set_point:设置文本构件的插入点gtk_text_get_point:获得文本构件的插入点gtk_text_get_length:返回当前文本的长度。

长度是整个文本的字符数,其中包括换行符gtk_text_insert:在当前点插入指定文本,其length参数为-1时将插入整个字符串gtk_text_backward_delete:删除当前插入点后指定个数的字符串gtk_text_forward_delete:删除当前光标前指定个数的字符gtk_editable_get_chars:获取文本构件中的一段文本。

GTK+中的事件(events)和信号(signals)

GTK+中的事件(events)和信号(signals)

GTK+中的事件(events)和信号(signals)在我们教程的这⼀个章节中,我们会谈⼀谈GTK+函数⼯具库中的,“事件”系统。

GTK+函数⼯具库是基于 “事件”系统的。

所有的 GUI 应⽤程序⽆⼀例外都是基于“事件”驱动的。

假如没有“事件”发⽣,则应⽤程序就什么都不会做。

在GTK+中⼀个事件就是从X窗⼝服务器传出来的⼀个消息。

当⼀个“事件”发⽣时,他就会通过发送⼀个“信号”来表⽰他已经做出了反应。

利⽤GTK+还可以为“信号”绑定专门的回调函数。

也就是说回调函数只对他特定的“信号”才有反应并执⾏。

#include <gtk/gtk.h>void button_clicked(GtkWidget *widget, gpointer data){g_print("clicked\n");}int main( int argc, char *argv[]){GtkWidget *window;GtkWidget *fixed;GtkWidget *button;gtk_init(&argc, &argv);window = gtk_window_new(GTK_WINDOW_TOPLEVEL);gtk_window_set_title(GTK_WINDOW(window), "GtkButton");gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);fixed = gtk_fixed_new();gtk_container_add(GTK_CONTAINER(window), fixed);button = gtk_button_new_with_label("Click");gtk_fixed_put(GTK_FIXED(fixed), button, 50, 50);gtk_widget_set_size_request(button, 80, 35);g_signal_connect(G_OBJECT(button), "clicked",G_CALLBACK(button_clicked), NULL);g_signal_connect(G_OBJECT(window), "destroy",G_CALLBACK(gtk_main_quit), NULL);gtk_widget_show_all(window);gtk_main();return 0;}在我们上⾯的这个⽰例应⽤程序中,我们有两个“信号”。

GTK入门

GTK入门

1. 简介GTK (GIMP Toolkit) 起源於开发用来做为GIMP (General Image Manipulation Program)的一套工具. GTK建立在GDK (GIMP Drawing Kit)的上层, 基本上是将Xlib功能包装起来. 它被称为GIMP toolkit是因为原来是写来开发GIMP, 但现在被许多免费软体计划所使用. 原作者为Peter Mattis petm@Spencer Kimball spencer@Josh MacDonald jmacd@GTK基本上是物件导向应用软体程式设计介面(API). 虽然完全用C所写成, 他是用classes及callback函数的观念所实作出来的(指向该函数).还有另一个被称为glib的函数库被用到, 该函数库包涵了一些标准X函数的替代函数, 及一些额外的处理链结表的函数等等. 这些替代函数是用来增加GTK的可移植性, 因为有些函数需要用到非标准的功能, 诸如g_strerror(). 有些则包含一些libc版本的加强的功能, 诸如g_malloc有加强的除错功能.这份导引是尽可能去详尽描述GTK的功能, 虽然实在没有办法尽善尽美. 这份导引假设读者对C语言有很相当的基础, 并且知道如何去写C语言程式. 如果读者有过X的程式经验, 会大大有帮助, 但并非绝对需要 (译注: 这一点就好像是要先学MFC或SDK的问题一样). 如果您以GTK做为进入X程式设计的入门的话, 请给我们一些建议, 有关於您在本导引所学到及发现的东西, 及过程中有何困扰. 同时, 目前GTK也有C++ API(GTK--)正在发展, 所以如果您喜欢用C++, 您可能要先去看一看. 同时也有一套Objective C wrapper, guile bindings版本也有, 但我不建议您走这条路.同时我也很想知道, 您在由本文学习GTK上有何问题, 我会感谢您告诉我如何改进这些种种的缺点.2. 开始第一件要做的是当然是取得一份GTK的原始码并且安装进您的系统中. 您可以从GIMP取得一份发行版, 或者是从Peter Mattis/"s的/"家中/" /pub/pmattis(however, it has been changed to )取得一份. GTK使用GNU的autoconf来设定. 一但您解开档案, 输入configure --help来看看选项表列.在介绍GTK的一开始, 我们尽可能挑最简单的程式. 这个程式将会产生200x200点的视窗, 而且没办法离开, 除非从shell中将它杀掉.#include <gtk/gtk.h>int main (int argc, char *argv[]){GtkWidget *window;gtk_init (&argc, &argv);window = gtk_window_new (GTK_WINDOW_TOPLEVEL);gtk_widget_show (window);gtk_main ();return 0;}所有程式理所当然一定会包含gtk/gtk.h, 其中宣告了所有变数, 函数, 及资料及结构. 这些东西您会在您的GTK应用软体中用到.下一行gtk_init (&argc, &argv);呼叫函数gtk_init(gint *argc, gchar ***argv)将会启动GTK. 该函数设定了一些内定的值, 并且後续交给gdk_init(gint *argc, gchar ***argv) 继续处理. 该函数启动了一些函数库以供使用, 设定了内定的信号处理, 检查传给您的程式的命令列参数. 看看以下:--display--debug-level--no-xshm--sync--show-events--no-show-events这些参数将会从参数表中删去, 所剩下的会传给您做後续的处理. 这样会产生标准的参数表(除了GTK所使用的)以供您使用.下面这两行程式会产生并显示一个视窗.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);gtk_widget_show (window);GTK_WINDOW_TOPLEVEL参数指定了我们承习视窗管理程式的外观. 即便我们产生一个0x0大小的视窗, 没有子视窗的视窗内定被设为200x200, 如此我们依然可以处理它.gtk_widget_show()函数, 让GTK知道, 我们已经处理完设定其属性的工作, 并且可以显示它.最後一行进入GTK的主要处理回圈.gtk_main ();gtk_main()是个在每个GTK应用软体中都会看到的一个函数. 当控制到达这里, GTK会/"睡/"一下来等待X事件的发生(诸如像按键被按下). 在我们最简单的例子里面, 事件会被忽略掉. 因为我们没有处理它.2.1 用GTK来写Hello World好, 现在我们来写一个有一个视窗物件的视窗(一个按钮). 这是个GTK的标准hello world. 这会建立起一个新的GTK 软体的良好基础.#include <gtk/gtk.h>/* 这是个callback函数. 其资料参数在本例中被忽略* 以下有更多的callback函数. */void hello (GtkWidget *widget, gpointer *data){g_print (/"Hello World//n/");}/* another callback */void destroy (GtkWidget *widget, gpointer *data){gtk_main_quit ();}int main (int argc, char *argv[]){/* GtkWidget用以储存视窗物件形态 */GtkWidget *window;GtkWidget *button;/* 这在所有GTK应用软体中用到. 参数由命令列中解译出来并且送到该应用软体中. */gtk_init (&argc, &argv);/* 产生新视窗 */window = gtk_window_new (GTK_WINDOW_TOPLEVEL);/* 当视窗收到/"destroy/"信号时(可由该软体或视窗管理程式所送出)所会被呼叫到的destroy函数一如以下所定义的一般.送到该函数的资料将会是NULL,并且在该函数中被忽略 */gtk_signal_connect (GTK_OBJECT (window), /"destroy/",GTK_SIGNAL_FUNC (destroy), NULL);/* 设定视窗的边框的宽度 */gtk_container_border_width (GTK_CONTAINER (window), 10);/* 产生一个新的按钮并带有/"Hello World/"的字在上面. */button = gtk_button_new_with_label (/"Hello World/");/* 当该按键收到/"clicked/"信号, 它会呼叫hello()这个函数.并且以NULL做为其参数. hello()函数在以上已定义过. */gtk_signal_connect (GTK_OBJECT (button), /"clicked/",GTK_SIGNAL_FUNC (hello), NULL);/* 这会导致当/"clicked/"这个按钮被按下的时候,呼叫gtk_widget_destroy(window)而使该视窗被关闭当然了, 关闭的信号会从此处或视窗管理程式所送来 */gtk_signal_connect_object (GTK_OBJECT (button), /"clicked/",GTK_SIGNAL_FUNC (gtk_widget_destroy),GTK_OBJECT (window));/* 这个动作会把这个按钮结合到该视窗(a gtk container). */gtk_container_add (GTK_CONTAINER (window), button);/* 最後一步是显示最新产生的视窗物件... */gtk_widget_show (button);/* 及该视窗 */gtk_widget_show (window);/* 所有GTK程式都一定要有gtk_main(). 所有控制结束於此并等带事件的发生(像按下一键或滑鼠的移动). */gtk_main ();return 0;}2.2 编译Hello World用以下命令来编译:gcc -Wall -g helloworld.c -o hello_world -L/usr/X11R6/lib //-lglib -lgdk -lgtk -lX11 -lXext -lm函数库必须在内定的搜寻路径内, 如果找不到, -L<library directory> 则gcc会去找这些目录, 看看所需要的函数库是否找得到. 例如, 在我的Debian Linux系统中, 我已经增加了 -L/usr/X11R6/lib用来寻找X11函数库.以下函数库是很重要的. linker在处理之前, 必须知道什麽函数要用那一个函数库.函数库如下:glib函数库(-lglib), 包含一些有用的函数, 这个例子中只用到g_print(), 因为GTK是建在glib之上, 所以您几乎都一定会用到它. 详见glib一段.GDK函数库(-lgdk), Xlib的包装程式.GTK函数库(-lgtk), 视窗物件函数库, 基於GDK之上.xlib函数库(-lXlib) 基本上为GDK所用.Xext函数库(-lXext). 包含了shared memory pixmaps及其它的一些X extensions.math函数库(-lm). 为GTK所用, 有多方面用途.2.3 Signals及Callbacks的原理在我们更进一步探讨hello world之前, 我们要讲一下事件(events)及回呼函数(callbacks). GTK本身是个事件驱动的工具, 这意味著它会在gtk_main进入停歇状态, 一直到一个事件发生, 并且将控制交给适当的函数来处理.控制权的交出是由/"signals/"来决定的. 当事件发生, 诸如按下滑鼠的一个按键, 对应的信号会由该视窗物件所送出. 这便是GTK的主要工作. 要使一个按下的动作执行一个命令, 我们设定一个信号处理函数来撷取这个信号, 并且呼叫适当的函数. 这工作是由像以下的函数来完成的:gint gtk_signal_connect (GtkObject *object,gchar *name,GtkSignalFunc func,gpointer func_data);其第一个参数是会送出信号的物件, 第二个是希望接取的信号名称. 第三个是当信号送出时的接取函数, 第四个则是要送给该函数的资料.第三个参数被称为/"callback function/", 而且必需是以下的形式:void callback_func(GtkWidget *widget, gpointer *callback_data);第一个参数是指向该物件的指标, 第二个是在gtk_signal_connect()的最後一个参数.另外一个在hello world中有用到的函数是:gint gtk_signal_connect_object (GtkObject *object,gchar *name,GtkSignalFunc func,GtkObject *slot_object);gtk_signal_connect_object()跟gtk_signal_connect()一样, 除了callback函术只有一个参数, 一个指向GTK物件的指标. 所以当使用这个函数来接到信号时, 该callback函数必须是以下形式:void callback_func (GtkObject *object);一般这个object是个widget(物件). 我们一般不设定callback给gtk_signal_connect_object. 他们是用来呼叫GTK 函数来接受单一物件(widget or object)做为参数.有两个函数来连接信号的目的只是希望允许callbacks可以有不同数量的参数. 许多GTK函数仅接受一个GtkWidget 指标做为参数, 所以您可以使用gtk_signal_connect_object()来使用这些函数, 而在您的函数里面, 您会需要额外的资料提供给callback.2.4 步过Hello World现在您知道这些理论了, 我们现在来根据这些理论, 把/"hello world/"这个范例弄清楚.这是个当按钮被按下时, 会被呼叫到的callback函数. 参数的资料没有被用到.void hello (GtkWidget *widget, gpointer *data){g_print (/"Hello World//n/");}这是另一个callback函数, 它会呼叫gtk_main_quit()来离开程式.void destroy (GtkWidget *widget, gpointer *data){gtk_main_quit ();}int main (int argc, char *argv[]){下个部份, 宣告一个指标给GtkWidget. 这是准备用来产生视窗及按钮的.GtkWidget *window;GtkWidget *button;这里是我们的gtk_init. 设定GTK toolkit初始值.gtk_init (&argc, &argv);产生新视窗. 这是蛮直接的. 记忆体配置给GtkWidget * window使其成为有效的资料. 它设定一个新的视窗, 但在我们呼叫gtk_widget_show(window)之前不会显示.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);这里是将object(window)连接到信号处理器的范例. 此处/"destroy/"是该信号. 该信号是window manager要销去这个视窗时, 或我们送出gtk_widget_destroy()时会产生的. 当我们这样设定时, 我们可同时处理两种状况. 这里我们使用destroy函数, 这使我们可以使用window manager来离开这个程式.GTK_OBJECT及GTK_SIGNAL_FUNC是分派巨集.gtk_signal_connect (GTK_OBJECT (window), /"destroy/",GTK_SIGNAL_FUNC (destroy), NULL);下一个函数是用来设定container物件的属性. This just sets the window so it has a blank area along the inside of it 10 pixels wide where no widgets will go. There are other similar functions which we will look at in the section on Setting Widget AttributesAnd again, GTK_CONTAINER is a macro to perform type casting.gtk_container_border_width (GTK_CONTAINER (window), 10);这个会产生一个新的按钮. 它配置记忆体给一个新的GtkWidget, 并初始化. 他将会有一个标签/"Hello World/".button = gtk_button_new_with_label (/"Hello World/");然後, 我们让这个按钮做一点事. 我们将他接到一个信号处理器, 因此它会送出/"clicked/"信号, 而我们的hello()函数会被呼叫到. 资料被忽略, 所以我们只喂NULL给hello(), 明显的, /"clicked/"信号当我们敲下滑鼠时被送出.gtk_signal_connect (GTK_OBJECT (button), /"clicked/",GTK_SIGNAL_FUNC (hello), NULL);我们将用这个按钮来离开程式. 这将展示/"destroy/"信号可以是来自window manager, 或是我们的程式. 当按钮被/"clicked/", 跟上面一样, 它会呼叫hello() callback函数, 然後是这一个, 以它们被设定的先後顺序被呼叫到. 您可以有任意个callback函数, 它们会以被连接的先後顺序被执行到. 因为gtk_widget_destroy()函数仅接受GtkWidget *widget做为参数, 我们使用gtk_signal_connect_object() , 而不用gtk_signal_connect().gtk_signal_connect_object (GTK_OBJECT (button), /"clicked/",GTK_SIGNAL_FUNC (gtk_widget_destroy),GTK_OBJECT (window));这是个封装呼叫, 我们在後面的文件中会解释. 不过这倒蛮容易理解的. 它就是告诉GTK按钮要放在要显示出来的那个视窗.gtk_container_add (GTK_CONTAINER (window), button);现在我们将所有东西照我们的意思来设定好了. 所有信号接好了, 按钮也放到该有的位置, 现在来/"show/"这个视窗吧. 这个整个视窗会一下子从萤幕蹦出来, 而不是先看到视窗, 然後按钮才跑出来.gtk_widget_show (button);gtk_widget_show (window);还有当然了, 我们呼叫gtk_main()来等待X事件的发生, 当事件发生时, 它将会呼叫物件来送出信号.gtk_main ();最後, 程式终止於此. 在gtk_quit()被呼叫到後, 程式会离开.return 0;现在, 当我们在GTK上敲下滑鼠, 这个物件会送出/"clicked/"信号. 我们的程式设定了信号处理器来接取这个信号, 这样我们便可利用这个资讯. 在我们的范例中, 当按钮被/"clicked/", hello()函数被呼叫到, 并被传入一个NULL参数, 然後下一个处理函数被呼叫到. 它会呼叫gtk_widget_destroy()函数, 传入视窗物件做为参数, 并将该视窗物件销毁. 这会导致该视窗送出/"destroy/"信号, 收到该信号後, 会呼叫我们的destroy() callback函数, 而我们的destroy()会令程式离开GTK.另一个方式当然是利用window manager来销毁该视窗. 这也会导致该视窗送出/"destroy/"信号, 然後呼叫destroy() callback, 然後离开.这些信号与UNIX系统不太一样, 并非基於UNIX系统的信号系统, 虽然它们的术语是一样的.3. 下一步3.1 资料型态有些东西您可能在前面的范例中已经看到, 这需要多解释一下. 像gint, gchar等等. 这些是为了取得绝对乾净的独立性, 如资料大小等等. 像/"gint32/"就是个很好的范例, 其目的是维持到任意平台均为32bits, 不管是64 bit alpha或是32 bit i386. 其定义是极其直接而且直觉的. 它们都被定义在glib/glib.h (被gtk.h所include).您也看到像在GtkWidget这一类的东西. GTK是物件导向的设计, 而widget则是其中的物件.3.2 更多关於信号处理函数我们来看看gtk_signal_connect宣告.gint gtk_signal_connect (GtkObject *object, gchar *name, GtkSignalFunc func, gpointer func_data);看到gint的返回值? 这是个标明您的callback函数的标签值. 像之前所说的, 每个信号及物件可以有好几个callback, 每个会以它们所接上的顺序被轮流执行到. 您可以用以下这个函数来移除这个callback函数:void gtk_signal_disconnect (GtkObject *object,gint id);你可以透过您想要移除的widget handler,给定id, 来解除信号处理函数.您也可以用:gtk_signal_disconnect_by_data (GtkObject *object,gpointer data);这玩意我倒没用过, 我真得不晓得要怎麽用 :)另一个函数可以解除所有的处理函数:gtk_signal_handlers_destroy (GtkObject *object);这个函数到底是自己解释了自己的功能. 它移除了该物件所有的信号处理函数.3.3 Hello World的加强版我们来看看一个稍经改良的hello world, 这是个callback的不错的例子. 这也会介绍到我们下一个主题, 封装物件.#include/* 新改进的callback. 输入到该函数的资料被输出到. */void callback (GtkWidget *widget, gpointer *data){g_print (/"Hello again - %s was pressed//n/", (char *) data);}/* another callback */void destroy (GtkWidget *widget, gpointer *data){gtk_main_quit ();}int main (int argc, char *argv[]){/* GtkWidget is the storage type for widgets */GtkWidget *window;GtkWidget *button;GtkWidget *box1;/* this is called in all GTK applications. arguments are parsed from * the command line and are returned to the application. */gtk_init (&argc, &argv);/* create a new window */window = gtk_window_new (GTK_WINDOW_TOPLEVEL);/* 这是个新函数, 它设定title到新视窗上/"Hello Buttons!/" */gtk_window_set_title (GTK_WINDOW (window), /"Hello Buttons!/");/* 用这样会比较简单一点. */gtk_signal_connect (GTK_OBJECT (window), /"destroy/",GTK_SIGNAL_FUNC (destroy), NULL);/* 设定边框宽度. */gtk_container_border_width (GTK_CONTAINER (window), 10);/* 我们产生一个box来封装物件. 这一点会在/"packing/"详述.这个box实际上看不见, 它只是用来当成是个工具来安排物件 */box1 = gtk_hbox_new(FALSE, 0);/* 将box放到主视窗中. */gtk_container_add (GTK_CONTAINER (window), box1);/* 产生一个新按钮并带有标签/"Button 1/". */button = gtk_button_new_with_label (/"Button 1/");/* 当按钮被按下的时候, 我们呼叫/"callback/"函数* 并以其指标做为参数送到/"button 1/" */gtk_signal_connect (GTK_OBJECT (button), /"clicked/",GTK_SIGNAL_FUNC (callback), (gpointer) /"button 1/");/* instead of gtk_container_add, we pack this button into the invisible * box, which has been packed into the window. */gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);/* always remember this step, this tells GTK that our preparation for * this button is complete, and it can be displayed now. */gtk_widget_show(button);/* do these same steps again to create a second button */button = gtk_button_new_with_label (/"Button 2/");/* call the same callback function with a different argument,* passing a pointer to /"button 2/" instead. */gtk_signal_connect (GTK_OBJECT (button), /"clicked/",GTK_SIGNAL_FUNC (callback), (gpointer) /"button 2/");gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);/* The order in which we show the buttons is not really important, but I* recommend showing the window last, so it all pops up at once. */gtk_widget_show(button);gtk_widget_show(box1);gtk_widget_show (window);/* rest in gtk_main and wait for the fun to begin! */gtk_main ();return 0;}将这个程式以相同的参数编译, 您会看到没有任何方法来离开程式, 您必须使用视窗管理程式或命令列来杀掉它. 对读者来说, 加个/"Quit/"按钮会是个不错的练习. 您也可以玩一玩gtk_box_pack_start()这个东西. 试试拉一拉视窗, 看看有什麽变换.另外有个蛮有用的define给gtk_window_new()用 - GTK_WINDOW_DIALOG. 它的互动行为有点不太一样.4. 封装物件当我们制作一套软体, 您会希望在视窗内放超过一个以上的按钮. 我们第一个范例/"hello world/"仅用一个物件, 因此我们能够很简单使用gtk_container_add来/"封装/"该物件到视窗中. 但当您希够望放更多的物件到视窗中, 要如何控制它们的位置? 这里就要用到/"封装/"(Packing).4.1 Packing Boxes的理论大部份的封装是由产生boxes来达成的. 这些是看不见的widget containers, 我们可以用两种形式来将我们的物件封装进去, vertical box及horizontal box. 当我们封装物件到一个horizontal box时, 物件是依我们呼叫的顺序由右至左平行的被新增进去. 在vertical box, 物件是由上至下. 您可以将物件插入box, 也可以将boxes插入box, 任意的组合用以产生所想要的效果.要产生horizontal box,我们使用gtk_hbox_new(), 而vertical boxe使用gtk_vbox_new(). gtk_box_pack_start()及gtk_box_pack_end()函数是用来将物件放到containers里面. gtk_box_pack_start()函数会开始由左至右, 由上至下来封装物件. gtk_box_pack_end()则相反, 由下至上, 由右至左. 使用这些函数允许我们对右边或对左边较正, 而且可以用许多种方式来较正来取得所想要的效果. 一个object可以是另一个container或物件. 而且事实上, 许多物件本身也是containers. 像按钮就是, 不过我们一般只在按钮中用一个标签.使用这些呼叫, GTK知道要把物件放到那里去, 并且会自动缩放及其它比例上的调整. 还有许多其它选项可以控制如何将物件封装在一起. 正如您所想的, 这些方法可以给您许多的弹性来制作视窗.4.2 Boxes详述由於这样的弹性, packing boxes在一开始使用的话会有点搞糊涂. 还有许多其它的选项,一开始还看不太出来它们如何凑在一起. 最後您会知道, 他们基本上有五种不同的型式.每一行包含一个horizontal box (hbox)及好几个按钮. 所有按钮都是以同样的方式来包入hbox内.这是gtk_box_pack_start的宣告.void gtk_box_pack_start (GtkBox *box,GtkWidget *child,gint expand,gint fill,gint padding);第一个参数是您要把object放进去的box, 第二个是该object. 现在这些物件将会都是按钮.expand 参数在gtk_box_pack_start()或gtk_box_pack_end()中控制物件如何在box中排列. expand = TRUE的话它们会填满box中所有额外的空间. expand = FALSE的话, 该box会缩小到刚好该物件的大小. 设expand=FALSE您可做好左右较正. 否则它们会填满整个box. 同样的效果可用tk_box_pack_start或pack_end functions来达成.fill参数在gtk_box_pack中控制额外空间. fill=TRUE该物件会自行产生额外空间, fill=FALSE则由box产生一个在物件周围的填白区域. 这只有在expand=TRUE时, 才会有作用.当产生一个新的box, 该函数看起来像这样:GtkWidget * gtk_hbox_new (gint homogeneous,gint spacing);homogeneous参数在gtk_hbox_new (and the same for gtk_vbox_new) 控制每个物件是否有同样的宽或高. 若homogeneous=TRUE, 则expand也会被开启.空白(spacing)及填白(padding)有什麽不同呢空白是加在物件之间, 填白只加在物件的一边. 看以下这张图可能会明白一点:这里是一些用来产生以上影像的程式. 我做了蛮多的注解, 希望您不会有问题. 将它编译然後玩玩它.4.3 封装示范程式#include /"gtk/gtk.h/"voiddestroy (GtkWidget *widget, gpointer *data){gtk_main_quit ();}/* Make a new hbox filled with button-labels. Arguments for the* variables we/"re interested are passed in to this function.* We do not show the box, but do show everything inside. */GtkWidget *make_box (gint homogeneous, gint spacing,gint expand, gint fill, gint padding){GtkWidget *box;GtkWidget *button;char padstr[80];/* create a new hbox with the appropriate homogeneous and spacing * settings */box = gtk_hbox_new (homogeneous, spacing);/* create a series of buttons with the appropriate settings */ button = gtk_button_new_with_label (/"gtk_box_pack/");gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button);button = gtk_button_new_with_label (/"(box,/");gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button);button = gtk_button_new_with_label (/"button,/");gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button);/* create a button with the label depending on the value of* expand. */if (expand == TRUE)button = gtk_button_new_with_label (/"TRUE,/");elsebutton = gtk_button_new_with_label (/"FALSE,/");gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button);/* This is the same as the button creation for /"expand/"* above, but uses the shorthand form. */button = gtk_button_new_with_label (fill ? /"TRUE,/" : /"FALSE,/"); gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button);sprintf (padstr, /"%d);/", padding);button = gtk_button_new_with_label (padstr);gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding); gtk_widget_show (button);return box;}intmain (int argc, char *argv[]){GtkWidget *window;GtkWidget *button;GtkWidget *box1;GtkWidget *box2;GtkWidget *separator;GtkWidget *label;GtkWidget *quitbox;int which;/* Our init, don/"t forget this! :) */gtk_init (&argc, &argv);if (argc != 2) {fprintf (stderr, /"usage: packbox num, where num is 1, 2, or 3.//n/"); /* this just does cleanup in GTK, and exits with an exit status of 1. */ gtk_exit (1);}which = atoi (argv[1]);/* Create our window */window = gtk_window_new (GTK_WINDOW_TOPLEVEL);/* You should always remember to connect the destroy signal to the* main window. This is very important for proper intuitive* behavior */gtk_signal_connect (GTK_OBJECT (window), /"destroy/",GTK_SIGNAL_FUNC (destroy), NULL);gtk_container_border_width (GTK_CONTAINER (window), 10);/* We create a vertical box (vbox) to pack the horizontal boxes into.* This allows us to stack the horizontal boxes filled with buttons one * on top of the other in this vbox. */box1 = gtk_vbox_new (FALSE, 0);/* which example to show. These correspond to the pictures above. */ switch (which) {case 1:/* create a new label. */label = gtk_label_new (/"gtk_hbox_new (FALSE, 0);/");/* Align the label to the left side. We/"ll discuss this function and* others in the section on Widget Attributes. */gtk_misc_set_alignment (GTK_MISC (label), 0, 0);/* Pack the label into the vertical box (vbox box1). Remember that * widgets added to a vbox will be packed one on top of the other in * order. */gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);/* show the label */gtk_widget_show (label);/* call our make box function - homogeneous = FALSE, spacing = 0, * expand = FALSE, fill = FALSE, padding = 0 */box2 = make_box (FALSE, 0, FALSE, FALSE, 0);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);/* call our make box function - homogeneous = FALSE, spacing = 0, * expand = FALSE, fill = FALSE, padding = 0 */box2 = make_box (FALSE, 0, TRUE, FALSE, 0);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);/* Args are: homogeneous, spacing, expand, fill, padding */box2 = make_box (FALSE, 0, TRUE, TRUE, 0);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);/* creates a separator, we/"ll learn more about these later,* but they are quite simple. */separator = gtk_hseparator_new ();/* pack the separator into the vbox. Remember each of these* widgets are being packed into a vbox, so they/"ll be stacked* vertically. */gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);gtk_widget_show (separator);/* create another new label, and show it. */label = gtk_label_new (/"gtk_hbox_new (TRUE, 0);/");gtk_misc_set_alignment (GTK_MISC (label), 0, 0);gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);gtk_widget_show (label);/* Args are: homogeneous, spacing, expand, fill, padding */box2 = make_box (TRUE, 0, TRUE, FALSE, 0);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);/* Args are: homogeneous, spacing, expand, fill, padding */box2 = make_box (TRUE, 0, TRUE, TRUE, 0);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);/* another new separator. */separator = gtk_hseparator_new ();/* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);gtk_widget_show (separator);break;case 2:/* create a new label, remember box1 is a vbox as created* near the beginning of main() */label = gtk_label_new (/"gtk_hbox_new (FALSE, 10);/");gtk_misc_set_alignment (GTK_MISC (label), 0, 0);gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);gtk_widget_show (label);/* Args are: homogeneous, spacing, expand, fill, padding */box2 = make_box (FALSE, 10, TRUE, FALSE, 0);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);/* Args are: homogeneous, spacing, expand, fill, padding */box2 = make_box (FALSE, 10, TRUE, TRUE, 0);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);separator = gtk_hseparator_new ();/* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);gtk_widget_show (separator);label = gtk_label_new (/"gtk_hbox_new (FALSE, 0);/");gtk_misc_set_alignment (GTK_MISC (label), 0, 0);gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);gtk_widget_show (label);/* Args are: homogeneous, spacing, expand, fill, padding */box2 = make_box (FALSE, 0, TRUE, FALSE, 10);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);/* Args are: homogeneous, spacing, expand, fill, padding */box2 = make_box (FALSE, 0, TRUE, TRUE, 10);gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);separator = gtk_hseparator_new ();/* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */ gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);gtk_widget_show (separator);break;case 3:/* This demonstrates the ability to use gtk_box_pack_end() to* right justify widgets. First, we create a new box as before. */box2 = make_box (FALSE, 0, FALSE, FALSE, 0);/* create the label that will be put at the end. */label = gtk_label_new (/"end/");/* pack it using gtk_box_pack_end(), so it is put on the right side* of the hbox created in the make_box() call. */gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);/* show the label. */gtk_widget_show (label);/* pack box2 into box1 (the vbox remember ? :) */gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);gtk_widget_show (box2);/* a separator for the bottom. */separator = gtk_hseparator_new ();/* this explicitly sets the separator to 400 pixels wide by 5 pixels* high. This is so the hbox we created will also be 400 pixels wide,* and the /"end/" label will be separated from the other labels in the* hbox. Otherwise, all the widgets in the hbox would be packed as* close together as possible. */gtk_widget_set_usize (separator, 400, 5);/* pack the separator into the vbox (box1) created near the start* of main() */gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);gtk_widget_show (separator);}/* Create another new hbox.. remember we can use as many as we need! */ quitbox = gtk_hbox_new (FALSE, 0);/* Our quit button. */button = gtk_button_new_with_label (/"Quit/");/* setup the signal to destroy the window. Remember that this will send* the /"destroy/" signal to the window which will be caught by our signal * handler as defined above. */gtk_signal_connect_object (GTK_OBJECT (button), /"clicked/",GTK_SIGNAL_FUNC (gtk_widget_destroy),GTK_OBJECT (window));/* pack the button into the quitbox.* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */ gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);/* pack the quitbox into the vbox (box1) */gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);/* pack the vbox (box1) which now contains all our widgets, into the* main window. */gtk_container_add (GTK_CONTAINER (window), box1);/* and show everything left */gtk_widget_show (button);gtk_widget_show (quitbox);gtk_widget_show (box1);/* Showing the window last so everything pops up at once. */gtk_widget_show (window);/* And of course, our main function. */gtk_main ();/* control returns here when gtk_main_quit() is called, but not when* gtk_exit is used. */return 0;}4.4 使用表格来封装我们来看看另一个封装的方法 - 用表格. 在很多状况下, 这是极其有用的.使用表格, 我们产生格线来将物件放入. 物件会照我们安排的位置排入.我们第一个要看的是gtk_table_new这个函数:GtkWidget* gtk_table_new (gint rows,gint columns,gint homogeneous);第一个参数是多少列, 第二个是多少栏.homogeneous 参数用来决定表格如何来定大小. 若homogeneous为TRUE, table boxes会被重定为在其中最大物件的大小. 若homogeneous为FALSE, 则其大小为, /"高/"为列中最高的物件, 及/"宽/"栏中最宽的物件大小.列及栏的编号为从0到n. n是我们在gtk_table_new中所指定的值. 所以, 如果您指定rows = 2及columns = 2, 整个排列会看起来像这样:0 1 20+----------+----------+| | |1+----------+----------+| | |2+----------+----------+坐标系统开始於左上角. 要把物件放进box中, 可用以下函数:void gtk_table_attach (GtkTable *table,GtkWidget *child,gint left_attach,gint right_attach,gint top_attach,gint bottom_attach,gint xoptions,gint yoptions,gint xpadding,gint ypadding);第一个参数(/"table/")是您才刚产生的表格, 而第二个(/"child/")是您想放进去的物件.而left_attach 及right_attach参数指定要把物件放在那里, 及用多少个boxes. 如果您想要用右下角的表格, 可以这样填表. left_attach = 1, right_attach = 2, top_attach = 1, bottom_attach = 2.现在, 如果您想要物件来使用上面2x2的表格, 您可以使用left_attach = 0, right_attach =2, top_attach = 0, bottom_attach = 1.xoptions及yoptions是用来指定封装选项, 可以同时组合多个选项(用or).这些选项是:GTK_FILL - 如果table box大过物件, 且GTK_FILL 被指定了, 该物件会扩展成使用所有可用的空间.GTK_SHRINK - 如果table widget小於该物件, (一般是使用者缩放该视窗), 那麽该物件将会一直被挤压到看不见为止. 如果GTK_SHRINK被指定了, 该物件会跟著table一起缩小.GTK_EXPAND - 这会使table本身扩展, 并利用视窗中所有可用空间.填空就像boxes, 产生一个在物件周边空白的区域.gtk_table_attach()有许多选项. 这里有个捷径:void gtk_table_attach_defaults (GtkTable *table,GtkWidget *widget,gint left_attach,gint right_attach,gint top_attach,gint bottom_attach);X及Y选项内定为GTK_FILL | GTK_EXPAND, X及Y填空则设为0. 其馀的参数则相同於以上的函数.我们另外有gtk_table_set_row_spacing()及gtk_table_set_col_spacing(). 这些会在指定的栏及列插入空白.void gtk_table_set_row_spacing (GtkTable *table,gint row,gint spacing);及void gtk_table_set_col_spacing (GtkTable *table,gint column,gint spacing);对栏来说, 空格是在栏的右边. 而列则是在下面.您也可以用以下函数来产生固定的空格.void gtk_table_set_row_spacings (GtkTable *table,gint spacing);及,void gtk_table_set_col_spacings (GtkTable *table,gint spacing);使用这些函数, 其最後一栏及最後一列并没有空格存在.4.5 Table Packing范例目前并无说明, 请参照testgtk.c5. 物件概论在GTK下,一般产生物件的步骤为:gtk_*_new - 最普遍产生物件的函数.连接信号到信号处理器.设定物件属性.要将物件包装到一个container可用gtk_container_add()或gtk_box_pack_start().gtk_widget_show().gtk_widget_show ()让GTK知道我们已经完成设定的工作, 并且已经准备好要显示. 您也可以用gtk_widget_hide来隐藏它. 显示物件的顺序并不太重要, 但我建议最後才显示, 这样才不会看到这些视窗们一个一个被画出来. 子物件在使用gtk_widget_show使视窗出现之前是不会被显示出来的.5.1 分派系统再继续下去您会发现, GTK使用一种分派系统. 一般是用巨集来完成. 您可以看到诸如以下:GTK_WIDGET(widget)GTK_OBJECT(object)GTK_SIGNAL_FUNC(function)GTK_CONTAINER(container)GTK_WINDOW(window)GTK_BOX(box)这些在函数中的都是分派参数. 您可以在范例中看到, 而且只要看到该函数就会知道它们是做什麽用的.从以下的组织图来看, 所有GtkWidgets都是由GtkObject而来. 这意味著您可以在任何地方, 透过GTK_OBJECT()巨集要求一个物件.例如:gtk_signal_connect(GTK_OBJECT(button), /"clicked/",GTK_SIGNAL_FUNC(callback_function), callback_data);这样分派一个按钮给一个物件, 并且提供一个指标给callback函数.许多物件同时也是containers. 如果您看看以下的组织图, 您会看到许多物件由GtkContainer而来所有这一类的物件都可以用GTK_CONTAINER巨集产生使用containers.5.2 物件组织图这里是一些参考, 物件组织图.GtkObject+-- GtkData| //-- GtkAdjustment|//-- GtkWidget+-- GtkContainer| +-- GtkBin| | +-- GtkAlignment| | +-- GtkFrame| | | *-- GtkAspectFrame| | || | +-- GtkItem| | | +-- GtkListItem| | | +-- GtkMenuItem| | | | +-- GtkCheckMenuItem| | | | *-- GtkRadioMenuItem| | | || | | *-- GtkTreeItem| | || | +-- GtkViewport| | //-- GtkWindow| | +-- GtkDialog| | //-- GtkFileSelection。

GTK:固定容器构件

GTK:固定容器构件

GTK:固定容器构件
GtkFixed(固定容器构件)允许将构件放在窗口的固定位置,这个位置是相对与窗口的左上角的。

构件的位置可以动态改变。

使用GtkFixed为构件定位,在大多数情况下都是不可取的。

因为当用户调整窗口尺寸时,勾结不能适应窗口的尺寸变化。

当然,你可以在窗口尺寸变化的时候采取行动,调整构件的位置和大小。

gtk_fixed_new函数用于创建新的固定容器构件。

1.
gtk_fixed_put函数将构件放在由x,y指定的位置。

2.
gtk_fixed_move函数将指定构件移动到新位置。

3.
程序运行后得到如下的窗体:
窗体每隔600毫秒便会扩大一次。

GTK:获取和修改标签文本

GTK:获取和修改标签文本
gtk_widget_show (button);
/*将组装盒加入窗体并显示所有构件*/
gtk_container_add (GTK_CONTAINER(window),box);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
/*新建标签*/
label = gtk_label_new ("Please check");
/*将标签放入组装盒*/
gtk_box_pack_start (GTK_BOX (box),label,FALSE,FALSE,15);
/*新建按钮构件*/
button = gtk_radio_button_new_with_label (group,"button1");
头文件:
#include <gtk/gtk.h>
函数原形:
void gtk_label_get(GtkLabel *label,char **str);
参数:
label要修改的标签构件
str标签构件的正文
返回值:

第一个参数是前面创建的标签构件,第而个参数是要返回的正文字符串。
下面我们结合上面的选择按钮编写一个如下图所示的程序:当用户点击选择按钮,上面的tabel显示相应的内容。
第一个参数是前面创建的标签构件第而个参数是要返回的正文字符串
GTK:获取和修改标签文本
创建标签构件后,要改变标签内的文本用gtk_label_set_text函数。
1.
名Hale Waihona Puke ::gtk_label_set_text
功能:

GTK:事件与信号

GTK:事件与信号

GTK:事件与信号Gtk所提供的工具库与Gtk应用程序与都是基于事件触发机制来管理。

所有的Gtk应用程序都是基于事件驱动,如果没有事件发生,应用程序将处于等待状态,不会执行任何操作,一旦事件发生,将根据不同的事件做出相应的处理。

在GTK+中,一个事件就是从X Server传出来的一个信息。

当一个事件发生时,Gtk程序就会通过发送一个信号来通知应用程序执行相关的操作,即调用指定控件与这一信号进行绑定的回调函数,来完成一次由事件所触发的行动。

一、GTK事件是如何产生以及传递的:1、Gtk应用程序如何能接收到来至XServer端的事件:根据以前的分析可知,GDK层所提供的事件循环对XServer端传过来的事件进行管理,并将其转化为GDK层的事件,通过对具体源代码的分析,可以知道Gtk应用程序能接收的事件,便是来自GDK层进行加工过的Gdk事件。

在程序中可以得知,当有事件需要处理时,Gdk层对XServer端的事件以队列的形式进行管理(_gdk_events_queue),并将X事件通过(gdk_event_translate)转换为GDK事件,将转换后的事件放入队列中,每次从队列中取出队首的事件(_gdk_event_unqueue),如果事件不为空,这时程序中的处理是将GDK事件GdkEvent交给了_gdk_event_func函数进行处理,到这我们可以知道,由XServer端产生的事件经过GDK层后将事件由一个函数_gdk_event_func来处理。

进一步分析知道,_gdk_event_func这一函数指针做为一个GDK 提供给外部的一个接口,外部程序如果实现这一接口,便可以接收来自GDK层转换XServer端产生的事件,在对Gtk的分析过程中,该接口是由Gtk来实现(gtk_main_do_event),也就是Gtk程序通过这一函数来处理事件。

当程序在调用gtk_init时对_gdk_event_func进行设置。

GTK、GDK、GLIB三者的关系收藏

GTK、GDK、GLIB三者的关系收藏

写成的,可以用于所有类UNIX系统,与图形相关的函数库依赖于X Window系统。

Gnome 函数库是最高层的。

GTK+由两部分组成,GTK和GDK。

GTK层为C语言提供了一个对象模型,并为UI工具包提供了最基本的widget,它是上层GUI派生的基础。

GTK是依赖于GDK 的,GDK是Xlib的一个底层包装,Xlib库直接与X服务器对话。

除了Xlib以外的任何部分都是基于GLib的,它是一个有用的C函数库,提供了很多实用程序和可移植的功能以及一组容易被C语言使用的容器。

一个Gnome程序使用多个库组成的层次结构:
Gnome库在最高层,包括帮助例程,类和特殊的widget,并为应用程序提供一个基础架构。

第二层是GTK,它是GTK+库的一部分。

这个库提供了基本的工具包和widget来创建GUI应用程序。

大多数GUI是直接用GTK编写的。

GTK同时为Gnome库提供了一个功能强大的对象系统。

再下一层是GDK,它简单的对X函数库进行了包装,只有在我们进行特殊绘画或设置窗口的特殊属性的时候才会用到它.
最下面一层是Glib,它是C的一个实用程序库,包括可移植性和一些实用程序功能,以及一些容器类,例如:链表,可变数组,变长字符串,HASH(貌似是哈西表),缓存,一个事件循环和其他有用的结构
GTK、GDK、GLIB三者的关系
/wtz1985/archive/2008/09/11/2915017.aspx。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

检查宏
gtk编程中有很多宏,一般都是类型检查作用。

如G_OBJECT,GTK_WINDOW,等等。

gtk_init()
初始化gtk参数。

gtk_init (&argc,&argv);
gtk_main()
gtk的循环函数,一直等待signal的到来,并处理:
gtk_main ();
gtk_main_quit()
退出gtk_main()
gtk_main_quit();
gtk_window_new()
这个函数每个gtk程序都需要,画一个window,这是最顶层的widget。

GtkWidget *window;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title()
设置窗口标题
gtk_window_set_title (GTK_WINDOW (window),"Hello Test!");
GTK_WINDOW是一个宏,负责检查window个的类型。

window是用gtk_window_new创建 的一个GtkWidget。

g_signal_connect()
信号处理函数,通过链接一个信号到一个回调函数,GTK可以完成用户的请求。

g_signal_connect (G_OBJECT (window),"delete_event",
G_CALLBACK (delete_event),NULL);
这里将窗口的delete-
event信号(通常是窗口管理器接受到用户点击关闭图标产生的窗口注销信号),链接到window 上(window一般都是gtk_window_new创建的)。

当有信号到到达是,执行delete_event回调函数。

并把NULL传递给delete_event作为参数。

gtk_container_set_border_width()
设置container(包容器)的边框,
gtk_container_set_border_width (GTK_CONTAINER (window),10);
gtk_hbox_new() 和 gtk_vbox_new()
一个创建横向盒子(一种包容器),一个创建纵向盒子。

GtkWidget *box;
box = gtk_hbox_new (FALSE,0);
gtk_button_new_with_label()
创建一个带标签的按钮。

GtkWidget *button;
button = gtk_button_new_with_label ("按钮1");
gtk_container_add()
向一个container里添加一个Widget
gtk_container_add (GTK_CONTAINER (window),box)
gtk_box_pack_start()
box的封装
gtk_box_pack_start (GTK_BOX (box),button,TRUE,TRUE,0);
gtk_widget_show()
显示一个Widget
gtk_widget_show (button);
gtk_widget_show (window);
gtk_widget_set_size_request()
设置一个widget大小
gtk_widget_set_size_request (clutter_widget, 200, 200);。

相关文档
最新文档