原文地址:http://blog.programet.org/2010/08/gtk-0.html
GTK+是当下流行的图形界面库之一,使用GTK+可以方便地构造出应用程序界面。叶子觉得GTK+很好用,在这里推荐给大家,并留下自己的一些使用心得。希望你也喜欢~
在Programet这个系列中,你可以看到GTK+通俗的介绍,了解使用方法和常用API,我们希望能对你有所帮助。下面是这个系列的内容线索(本系列不断更新中,这个列表可能随更新而有少量变化):
- 构建GTK+编译环境
- GTK+“Hello World”——对GTK+运作机制的通俗介绍
- 使用GtkBuilder、界面设计器Glade和其他GTK+组件
- GTK+常用物件及API(窗口)
- GTK+常用物件及API(文本)
- GTK+常用物件及API(按钮)
- GTK+常用物件及API(其他)
- GLib中的小工具
- 使用gettext实现国际化和制作语言包
- 【高级主题】使用GDK访问底层屏幕和事件
- 【高级主题】使用gtk-pixbuf处理图像和图像文件
- 【高级主题】使用GIO中的GSocket访问网络
- 【高级主题】使用cairo绘图
上面的列表中并没有“GTK+介绍”一项,因为我要在这篇文章后半部分完成它!
GTK+究竟能做什么
GTK+是图形界面库,能帮助我们简洁方便地绘制窗口和里面的输入框、按钮等等。这能减少我们很多麻烦——有经验的童鞋可能深有体会,图形界面几乎是应用程序编写中最繁琐的部分。图形界面库就是为了方便我们组织界面而出现的,使用它可以大大减少我们花在组织界面上的代码量。
同时,GTK+可以配合界面设计器Glade,换句话说,做界面不用敲冗长的代码,界面可以画出来!
更重要的是,GTK+是跨平台的。只要代码写得标准,在Windows、Linux和Mac OS下,不用做任何修改就可以展现出同样的界面,方便吧~
GTK+支持的
GTK+是一个开源跨平台的库,支持很多平台,这里就不一一列举了。它遵循LGPL协议,也就是说我们可以自由地使用它,使用它制作的程序可以自行选择开源与否。
GTK+是用C语言编写的,很多GTK+应用程序也使用C语言完成。但如果你讨厌C语言的话,你同样可以选用其他多种语言,包括C++、Java、Python等等,甚至还可以是PHP。而且在各种语言中的API很相似,这让我们在各种语言下玩GTK+变得很方便。
谁在用GTK+
GTK+现在为很多软件所使用,最典型的是Linux桌面环境GNOME和Xfce,包括在它们中运行的众多软件(很多时候GNOME和Xfce软件可以混用,因为他们都是GTK+的)。
还有号称“开源PS”的GIMP、矢量图编辑器Inkscape等等,还有只是使用部分GTK+库(尤其是GLib)的众多软件,还有偷偷拿GTK+代码来用的软件……
与GTK+相似的图形界面库
目前,还有很多流行的图形界面库:
- MFC——微软的一个C++库,很多人用,但功能落后,也被讽刺为“半成品”。
- Qt——大红大紫的一个图形界面库,各方面表现都很好。现归属于Nokia。(传说很久很久以前QT和GTK+的支持者喜欢对骂……)
- WxWidgets——个人认为这个库灰常强大!它在不同操作系统中都可以生成“原生”的界面,甚至不需要运行库!只是有人说不稳定……
还有其他的一些,这里就不提了吧。
毫无疑问的是,GTK+是它们中很有特点的一个。你很难找出第二个C语言图形界面库。GTK+以架构严谨优秀高效著称,是GNU项目的一部分,像是很标准的GNU式的开源项目。它和GNU项目中的其他部分配合良好,遇到麻烦时,常常可以让其他库帮忙。
GTK+的历史与前景
GTK+是1999年开始发展的一个项目,在图形界面库中算很年轻的,但是发展飞速,以至于网络上对其的描述都难以跟上其发展(现在搜索到的很多描述不正确)。GTK+一直由社区维护,但同时又备受众多商业公司青睐,应用领域在不断扩展中。
有关本系列
在这一系列文章中,GTK+原生语言——C语言将被用来举例,其他语言使用方法类似,具体请参见不同语言的文档。这也要求读者能熟练运用C语言。
文章中的例子使用Windows下的GTK+ 2.16(GLib 2.24)编译通过,并特别照顾Windows下的配置、使用,相较而言,在Linux下的配置、使用简单一些。
原文地址:http://blog.programet.org/2010/08/gtk-1.html这一部分介绍的是在Windows/Linux下配置GTK+(C语言)编译及运行环境的方法。如果内容存在错误,或者方法不适用与你的电脑,请在下方评论区留言给我,谢谢!
在Linux下配置GTK+编译环境
Linux的X Window是GTK+主要应用的地方,在Linux下配置GTK+应该是比较容易成功的。当然,你的Linux需要有GNOME或Xfce这样的桌面环境(不建议在KDE下运行GTK+应用程序)。
如果你的Linux像Ubuntu这样有一个软件库,那就太方便了,直接安装包libgtk2.0-dev即可。如果不能直接安装软件包,你还可以直接到http://www.gtk.org/download-linux.html下载,那个安装指南会对你有帮助的。
然后是编辑器的问题。像Anjuta这样的编辑器可以直接创建GTK+项目,你可以利用这个功能,很方便。如果你的编辑器不能创建GTK+项目,或者你根本不打算用编辑器,你可以用pkgconfig命令获得你用gcc编译时所需的参数:
pkg-config --cflags --libs gtk+-2.0 |
这一系列以后的文章中会用到Glade界面设计器,请安装包glade或到http://ftp.gnome.org/pub/GNOME/sources/glade3/3.6/下载Source来编译。要注意的是,Glade本身也是一个GTK+应用程序,需要在GTK+的桌面环境中运行。
在Windows下配置GTK+编译环境
在Windows下配置编译环境就有些麻烦。这里看来要用支持创建GTK+项目的编辑器来帮忙了。
这里介绍在Code::Blocks编辑器和MinGW GCC编译器下编译GTK+程序的方法。(其实在Visual Studio下也可以编译GTK+的,但是这里不推荐。)
装好Code::Blocks
如果你不熟悉Code::Blocks,建议看看我以前写的这篇文章。
安装GTK+开发库和Glade界面编辑器
这里介绍一个简单的方法。Glade有的发布版直接包含有GTK+开发库。到Glade主页http://glade.gnome.org/右边的Windows Binaries中找Glade3-x.x.x-with-gtk.exe这样的版本下载安装。建议装到C:\gtk\。
但是可能Glade自带的GTK+开发库不是最新的,无法实现一下高版本的GTK+提供的功能,因此最好到GTK+下载页http://www.gtk.org/download-windows.html下载一个All-in-one bundles。下载下来之后直接解压到刚刚Glade的安装目录即可。
在Code::Blocks中建立GTK+项目
Code::Blocks中,File->New->Project中应该会有GTK+ Project这一选项。按着向导新建即可,但要注意几个地方:项目文件完整路径必须是英文的,Code::Blocks对中文路径和文件名支持不佳;GTK’s location必须指定为你刚刚安装的GTK+开发库所在文件夹。
测试你的编译环境
就拿Code::Blocks为我们自动生成的这段程序做测试吧:
#include <stdlib.h> #include <gtk/gtk.h> static void helloWorld (GtkWidget *wid, GtkWidget *win) { GtkWidget *dialog = NULL; dialog = gtk_message_dialog_new (GTK_WINDOW (win), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "Hello World!"); gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } int main (int argc, char *argv[]) { GtkWidget *button = NULL; GtkWidget *win = NULL; GtkWidget *vbox = NULL; /* Initialize GTK+ */ g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, (GLogFunc) gtk_false, NULL); gtk_init (&argc, &argv); g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, g_log_default_handler, NULL); /* Create the main window */ win = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_container_set_border_width (GTK_CONTAINER (win), 8); gtk_window_set_title (GTK_WINDOW (win), "Hello World"); gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_CENTER); gtk_widget_realize (win); g_signal_connect (win, "destroy", gtk_main_quit, NULL); /* Create a vertical box with buttons */ vbox = gtk_vbox_new (TRUE, 6); gtk_container_add (GTK_CONTAINER (win), vbox); button = gtk_button_new_from_stock (GTK_STOCK_DIALOG_INFO); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (helloWorld), (gpointer) win); gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); button = gtk_button_new_from_stock (GTK_STOCK_CLOSE); g_signal_connect (button, "clicked", gtk_main_quit, NULL); gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); /* Enter the main loop */ gtk_widget_show_all (win); gtk_main (); return 0; } |
这段程序会建立一个有两个按钮的窗口。Windows下还会另外有个小黑窗口,方便调试用的;指定Build->Select target->Release之后再编译,编译出来的“Release”版本就没有小黑窗口了。
如果你编译失败——不幸,但是你可以在下面留言给我。
在Windows下制作一个GTK+运行环境
你需要明白的是,GTK+是需要运行库的——Linux下一般都会自带有,Windows下就没那么幸运了。如果你的程序需要在别人的电脑上运行,你往往需要附带一个GTK+运行库,运行库的制作方法是把http://www.gtk.org/download-windows.html中的所有Binary组合起来。
为了方便大家,我自己做了一个运行库,经过一定精简(只有中英两种语言),大小13MB(压缩后3MB)。大家可以到这里下载。
用法就是把程序及程序用到的文件放进来,使程序与运行库的那堆dll在同一级文件夹下。然后整个文件夹就可以作为便携软件在不含GTK+的Windows中使用了。
另外,GTK+运行库是支持主题的。你可以为GTK+指定主题,给那些按钮换一个样子。GTK+主题文件位于运行库的\etc\gtk-2.0文件夹中,名为gtkrc。我制作的运行库指定了GTK+使用Windows主题。你可以在网上搜出很多GTK+ themes,使用方法就是替换gtkrc文件。
原文地址:http://blog.programet.org/2010/09/gtk-2.html
这一部分是对最简单的GTK+(C语言)程序的一个解释,并介绍GTK+的基本概念和运作方式。如果内容存在错误,或者方法不适用与你的电脑,请在下方评论区留言给我,谢谢!
几个概念
首先先来解释GTK+中几个基本的概念,以方便将来的分析。
物件(GtkWidget):GTK+中每一个窗口里的组成要素都被视为一个物件,如按钮、文本等等,窗口本身也是一个物件。总之GTK+的界面就是由物件构成的。注意,物件都使用指针来管理,物件外在表现就是一个特定类型的指针。
容器(GtkContainer):物件里的一大类,容器的特点是其内部能够容纳其他物件。容器最基本的功能之一是将各种物件良好地组织起来。GTK+的容器能在大小改变时自动调整内含物件的大小,这使得GTK+能够很智能地相应窗口或其他物件的大小改变。这为我们提供了很大的方便,往往我们不需要指定某个物件的大小,只需说明他所在的容器位置,GTK+会把物件的实际位置和大小自动计算出来(这比MFC强多了!)。
继承、组合:虽然是C语言写的,但GTK+灵活地运用了面向对象思想。GTK+的物件体系中就有继承、组合这样的关系,如窗口(GtkWindow)是由容器(GtkContainer)派生出来的。
类型转换宏:C语言本身没有“继承”这个概念,那么,如果直接把派生的物件直接当做基物件使用,会出现一个编译警告,即“隐式指针类型转换”,但不会出错。为了消除这个警告,需要做指针类型转换。一般情况下类型转换使用类型转换宏。类型转换宏内部会检查物件的继承关系,确定能否进行转换,然后再做显式类型转换。
事件(event):用户的操作,比如按下某个按钮或快捷键,被视为一个事件。
信号(signal):GTK+是基于信号回调(signal-slot)机制的。信号捆绑了一个事件和一个函数,在用户触发这个事件时,这个函数会被调用一次。从这个角度来说,GTK+是基于物件的,即程序围绕物件属性、事件、方法进行。
主循环(main loop):GTK+程序在一个主循环中运行。当一个事件被触发时,它将被插入队列中;在主循环中被触发的事件会被逐个处理(和这个事件绑定的函数被逐个调用);没有事件被触发时,程序就处于等待状态,等待下一个事件被用户触发。直到退出主循环的函数被调用,GTK+程序才结束。
GTK+命名规范
GTK+拥有开源软件的很多特点,比如结构高度严谨,可读性甚好。现在介绍一下GTK+的关键字命名方式,以便阅读一段GTK+程序。
普通变量类型名:全小写写法,以“g”开头,如“gint”。
物件类型名:驼峰写法(首字母大写),以“Gtk”开头,形如“GtkWindow”。在GTK+内部,类型是向下面这样定义的(以GtkWindow为例)。
typedef _GtkWindow { ... } GtkWindow; |
函数名:小写夹下划线写法,以“gtk_”为前缀,形如“gtk_main()”。如果是针对某类物件的函数,则前缀中还有物件类型名,形如“gtk_window_new()”。
常数名:大写夹下划线写法,以“GTK_”为前缀,形如“GTK_WINDOW_TOPLEVEL”。
类型转换宏:大写夹下划线写法,以“GTK_”为前缀。一般来说,宏名字和类型名相仿,比如要把GtkWindow*类型的物件转换为GtkContainer*类型,就使用宏“GTK_CONTAINER()”。
GTK+的“Hello World”
下面这段程序是GTK+的Hello World,它创建一个普通窗口,里面只有一句“Hello, World”。在前文的基础上,可以分析一下这一段Hello World。
//下面来分析一下这其中每句话的含义,介绍如何初始化GTK+,使C语言程序在GTK+环境下运行。 #include <gtk/gtk.h> //包含gtk库 int main (int argc, char *argv[]) { GtkWidget *window; GtkWidget *label; //定义两个物件指针,用于操作物件。 //这一句是所有GTK+程序必须的:初始化GTK+库。每个GTK+程序必须用这个来使GTK+做好准备。 gtk_init (&argc, &argv); //接下来这三句用于建立并设置一个窗口,几乎所有的GTK+程序都要新建窗口。 //建立一个新窗口,让window指向它。之后window就相当于这个窗口了。目前窗口中不包含任何物件。 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //设置window标题为“Hello World”。 //这里使用了类型转换宏GTK_WINDOW()。因为这里函数参数需要是GtkWindow*型,而window在定义的时候是GtkWidget*型的。 gtk_window_set_title (GTK_WINDOW (window), "Hello World"); //连接信号:将window的关闭(destroy)事件与退出主循环函数gtk_main_quit()绑定在一起,即窗口被关闭时程序结束。 //G_CALLBACK()也是一个类型转换宏,它把普通函数变成信号回调函数。 g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); //接下来写入窗口内容。窗口只包含一个文本(GtkLabel)。 //新建一个GtkLabel,让label指向它。之后label就相当于这个文本了。 label = gtk_label_new ("Hello, World"); //把label插入母容器中。把window转换为容器(这是允许的,因为GtkWindow由GtkContainer派生),然后插入label。 gtk_container_add (GTK_CONTAINER (window), label); //接下来这两句也是所有GTK+程序必须的。 //显示所有物件。物件新建好后是隐藏的,用这个函数来显示window及它包含的内容。 gtk_widget_show_all (window); //进入主循环,开始接受用户操作并处理各种事件。 gtk_main (); return 0; } |
程序内容很简洁,它只处理一个事件:关闭窗口。但是这个程序已经摆出了GTK+程序主函数编写的基本形式:使用gtk_init()初始化;建立窗口、组织窗口内容并连接信号;显示窗口;进入主循环。此外,编写回调函数并动态修改窗口内容通常也是必须的。基本所有GTK+程序都遵循这个规律。
可以想见的是,建立窗口、组织窗口内容是非常麻烦的事情。于是界面设计器应运而生,使得组织界面的工作不再由代码完成。下一部分内容会介绍使用界面设计器Glade的方法。
另外,有关GTK+物件、函数、常数的说明都可以在GTK+参考中找到。记得收藏GTK+参考的网址http://library.gnome.org/devel/gtk/stable/index.html,将来查找函数就靠它了!
原文地址:http://blog.programet.org/2010/09/gtk-3.html
这一部分包括GTK+相关组件的简要介绍,和界面设计器的使用方法。如果内容存在错误,或者方法不适用与你的电脑,请在下方评论区留言给我,谢谢!
GTK+的姊妹库
准确地说,GTK+仅指一个界面物件库。为了制作GTK+,一些副产品相继诞生,比如C语言界很有名的的GLib库。这些GTK+的“姊妹库”都是GTK+所依赖的,而且,制作GTK+程序时可能需要直接使用这些库。
- GLib:目前最好的C语言数据结构库之一。除数据结构外,它还包括许多常用小工具,比如多线程管理、定时器。GTK+界面无关的部分基本都被并入GLib中。
- GIO:GLib库相对独立的一部分,专门处理输入输出流。新版本的GIO还包括了网络连接功能。
- GObject:GLib库相对独立的一部分,维护一套对象系统。GTK+疯狂地使用这个系统。
- ATK:ATK提供一组查看和控制接口以方便对GTK+程序的访问。
- pango:负责处理GTK+中和字体有关的部分。
- cairo:著名的2D渲染库,被Firefox等很多程序使用。它也是目前GTK+使用的2D渲染库,通过它可以进行矢量绘图。
- gdk-pixbuf:GDK的一个部分,提供了一组位图函数,包括位图变换、位图文件读写等等。
- GDK:提供一组接口,把GTK+从桌面系统细节中隔离出来。它是一组底层函数,可以直接访问窗口细节。GTK+系统有关的部分多数在这里。
这些库的API参考都可以在GNOME参考(http://library.gnome.org/devel/references.html.zh_CN)中找到。
还有一些库是GTK+依赖的第三方库,下面是几个重要的。
- gettext:国际化库。主要用于制作多语言程序。运行时gettext自动识别操作系统语言,然后从已有语言包中选择一个最合适用户的。
- iconv:字符集转换库。GTK+内部使用UTF-8字符集,有时需要字符集转换。
GTK+内部构成
GTK+本身只负责界面组织。它提供的函数大致可分为三类,物件(Widget)、对象(Object)和其它工具函数。
工具函数提供一些与界面关系密切的实用功能,比如剪贴板读写。
对象是一些功能更加复杂的不可见元素,它们和界面息息相关,比如GtkBuilder。
界面设计器Glade
通过代码来组织界面繁琐而不直观,因而有人为GTK+做了一款界面设计器,名为Glade,现已成为GTK+最重要的辅助工具。
接下来用一个计算器制作的实例来讲解GTK+界面设计器的使用方法。
打开Glade。Glade会自动新建一个文件,新建后会弹出对话框设置文件格式,应选用GtkBuilder。
首先建一个窗口。在左栏中找到“窗口”一项,点一下即可。中间部分的黑框即为窗口中的内容。
下面要组织窗口中的内容了。要注意的是,一个灰色区域只能放置一个物件。如果需要放置多个物件,可以使用水平框、垂直框或表格物件,这些容器可以把一个灰色区域分成多个。
添加Spin按钮(Spin按钮用于输入数字)、表格、按钮等物件,可以把界面画成想要的样子,在右下方的属性设置中,可以设置物件的各种属性。在“常规”选项卡中,可以设置一些重要的初始值,物件名等。注意:需要动态更改的物件,物件名很重要。
“包装”选项卡负责物件的间距控制和大小改变方式等。GTK+在窗口大小改变时会智能地调整物件大小,其依据的就是这个选项卡里的设置。
计算器的界面成形了。记得经常保存,Glade有时会比较脆弱。
注意:在输入完某项属性之后务必使输入焦点离开当前输入区,然后才可以保存文件,否则当前输入区的更改不会被立即保存到文件中。
载入界面
Glade文件的本质是个XML文件,这个文件可以用GtkBuilder对象载入并生成界面。下面这样写可以载入一个Glade文件。
GtkBuilder* gtk_load_glade(gchar* filename) { GtkBuilder *gb; //新建一个GtkBuider对象 gb=gtk_builder_new(); //载入文件,失败则返回NULL if(!gtk_builder_add_from_file(gb,filename,NULL))return NULL; //连接文件中包含的所有信号 gtk_builder_connect_signals(gb,NULL); //返回GtkBuilder对象供后面操作使用 return gb; } |
载入后还需要还需要获得已载入的物件地址,并将储存在物件指针里以便以后动态更改物件。一个聪明的策略是使指针名字和物件在Glade里设置的名字一样。用函数gtk_builder_get_object()可以获得指定名字的物件地址。为了简便,可以写一段宏代替冗长的函数调用。下面这段代码演示了获得主窗口(名为WMain)和Spin按钮(名为SAns)地址的方法。
#define w_(builder,type,name) name=GTK_##type(gtk_builder_get_object(builder,#name)) GtkWindow *WMain; GtkSpinButton *SAns; void cal_get_widgets(GtkBuilder* gb) { w_(gb,WINDOW,WMain); w_(gb,SPIN_BUTTON,SAns); } |
主窗口开始时是不显示的,应该用下面这个函数把它显示出来。下面这个函数只能在获得物件地址后执行。
void cal_widget_init() { gtk_widget_show(GTK_WIDGET(WMain)); } |
编写回调函数
现在的主要任务就是编写回调函数——这些函数才是程序的主角。在某个事件被触发时,对应的函数会被执行。这个函数可以在Glade中指定。在Glade中选定某个物件,然后在右下角“信号”选项卡中选择一个合适的事件,在“操作句柄”列填入函数名。
下面为窗口WMain指定destroy事件的回调函数on_WMain_destroy()。
然后编写一个函数on_WMain_destroy()。在Windows下,这个函数要加上修饰词G_MODULE_EXPORT。
G_MODULE_EXPORT void on_WMain_destroy(GtkObject* widget, gpointer user_data) { gtk_main_quit(); } |
这个回调函数只是退出程序而已。最后献上一段main()。
int main(int argc, char *argv[]) { GtkBuilder *gb; gtk_init(&argc,&argv); gb=gtk_load_glade("gtk-cal.glade"); if(gb==NULL)return -1; cal_get_widgets(gb); cal_widget_init(); gtk_main(); return 0; } |
这个计算器程序目前只完成了最基本的部分,这个系列后续的文章会把它做完。有关回调函数、物件函数的信息,请参考GTK+ API参考。
学习使用GTK+ 4.GTK+常用物件及API(窗口)
原文地址:http://blog.programet.org/2010/10/gtk-4.html这一部分内容介绍有关GTK+常用窗口类物件的一些函数。如果对内容有疑问,请在下方留言,谢谢!
GTK+的窗口
窗口是GTK+最基本的物件之一,物件要被放在窗口里显示。GTK+里,常用的窗口包括顶级窗口(GtkWindow)、对话框(GtkDialog)和消息对话框(GtkMessageDialog)等。
GTK+有关窗口的操作很多,绝大多数情况下可以满足自定义窗口的需求;但有时候还是不可避免要直接访问底层库GDK。要注意的是,GdkWindow与GtkWindow有很大差异,GdkWindow指一个显示区域,每一个可显示的GTK+物件都对应一个GdkWindow,阅读文档时两者不可混淆。
窗口类物件在Glade中得到了良好的支持,复杂的窗口建议直接用Glade创建。
简易消息对话框
消息对话框是最简易的窗口,如果还在Glade中创建的话,很麻烦且会使Glade文件变得更大。下面这些函数,可以快速创建一个窗口而不需要Glade。
void gtk_show_info(gpointer window, const gchar* message, const gchar* title) { GtkWidget *dialog; dialog = gtk_message_dialog_new_with_markup(window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, message); gtk_window_set_title(GTK_WINDOW(dialog), title); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(GTK_WIDGET(dialog)); } void gtk_show_error(gpointer window, const gchar* message, const gchar* title) { GtkWidget *dialog; dialog = gtk_message_dialog_new_with_markup(window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, message); gtk_window_set_title(GTK_WINDOW(dialog), title); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } gint gtk_show_question(gpointer window, const gchar* message, const gchar* title) { gint i; GtkWidget *dialog; dialog = gtk_message_dialog_new_with_markup(window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, message); gtk_window_set_title(GTK_WINDOW(dialog), title); i=gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if(i==GTK_RESPONSE_YES) return 1; else return 0; } void gtk_show_warning(gpointer window, const gchar* message, const gchar* title) { GtkWidget *dialog; dialog = gtk_message_dialog_new_with_markup(window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, message); gtk_window_set_title(GTK_WINDOW(dialog), title); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } |
以上四个函数分别是一个信息窗口、错误提示窗口、询问窗口、警告窗口,三个参数分别是母窗口、窗口内文字内容、窗口标题。在程序中直接调用函数即可。
文件选择对话框
文件选择对话框同样可以不用Glade创建,而直接调用API方便地创建。下面的函数可以创建文件打开对话框和文件保存对话框。
GtkWidget* gtk_show_file_add_filter(GtkWidget* dialog, const gchar *description, gchar *pattern) { GtkWidget *filter; filter=GTK_WIDGET(gtk_file_filter_new()); gtk_file_filter_set_name(GTK_FILE_FILTER(filter),description); gtk_file_filter_add_pattern(GTK_FILE_FILTER(filter),pattern); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),GTK_FILE_FILTER(filter)); return filter; } gchar* gtk_show_file_open(GtkWidget* parent_window, const gchar *title, const gchar *filters) { GtkWidget *dialog,*FF[16]; gchar *filename,des[256],pattern[64]; long i,j,FFc=0; dialog = gtk_file_chooser_dialog_new (title, GTK_WINDOW(parent_window), GTK_FILE_CHOOSER_ACTION_OPEN, /*GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,*/ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); //filters for(i=0;i<strlen(filters);i++) { j=0; while(i<strlen(filters) && filters[i]!='|') des[j++]=filters[i++]; if(j>=256)break; des[j]=0; j=0; i++; if(i>=strlen(filters))break; while(i<strlen(filters) && filters[i]!='|') pattern[j++]=filters[i++]; if(j>=64)break; pattern[j]=0; FF[FFc++]=gtk_show_file_add_filter(dialog,des,pattern); if(FFc>=16)break; } if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); gtk_object_destroy(GTK_OBJECT(dialog)); return filename; } return NULL; } gchar* gtk_show_file_save(GtkWidget* parent_window, const gchar *title, const gchar *default_folder, const gchar *default_name, const gchar *filters) { GtkWidget *dialog,*FF[16]; gchar *filename,des[256],pattern[64]; long i,j,FFc=0; dialog = gtk_file_chooser_dialog_new (title, GTK_WINDOW(parent_window), GTK_FILE_CHOOSER_ACTION_SAVE, /*GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,*/ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); if(default_folder[0]!=0)gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_folder); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_name); //filters for(i=0;i<strlen(filters);i++) { j=0; while(i<strlen(filters) && filters[i]!='|') des[j++]=filters[i++]; if(j>=256)break; des[j]=0; j=0; i++; if(i>=strlen(filters))break; while(i<strlen(filters) && filters[i]!='|') pattern[j++]=filters[i++]; if(j>=64)break; pattern[j]=0; FF[FFc++]=gtk_show_file_add_filter(dialog,des,pattern); if(FFc>=16)break; } if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); gtk_widget_destroy (dialog); return filename; } //destroy gtk_widget_destroy (dialog); for(i=0;i<FFc;i++) gtk_object_destroy(GTK_OBJECT(FF[i])); return NULL; } |
gtk_show_file_open()建立一个文件打开窗口供用户选择文件,参数依次是母窗口、标题、过滤器。
gtk_show_file_save()建立一个文件保存窗口供用户选择文件,参数依次是母窗口、标题、默认文件夹、默认文件名、过滤器。
其中“过滤器”是一串字符,字符内用“|”分离,其形式像这样:文件类型名称1|对应通配符1|文件类型名称2|对应通配符2|……
使用GDK函数
GTK+提供好了丰富的功能,但也有缺陷——某些常用功能无法直接使用,需要访问GDK库。下面这个函数,用来确定窗口是不是处于全屏状态。
gboolean gtk_window_is_fullscreen(GtkWindow* window) { return (gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(window))) & GDK_WINDOW_STATE_FULLSCREEN) == GDK_WINDOW_STATE_FULLSCREEN; } |
其他用法,请参阅GTK+参考。