一.GTK库
GTK (GIMP Toolkit) 是一套开源的跨平台图形用户界面 (GUI) 工具包,最初是为 GNU 图像处理程序 (GIMP) 设计的。它提供了一组可重用的 GUI 元素(例如按钮、文本框、下拉列表、进度条等),可以用于开发各种类型的应用程序。
GTK 库是基于对象的,并采用 C 语言编写。它还有许多其他编程语言的封装,如 Python、Perl 和 Ruby 等。GTK 库支持运行在 Linux、UNIX、Windows 和 macOS 等平台上,并且与许多开源和商业软件项目一起使用。
GTK 库还包含一些附加功能,例如用于绘制二维图形的 Cairo 库、用于解析 XML 的 LibXML2 库、以及用于处理国际化和本地化的 Gettext 库。因此,GTK 库不仅仅是一个 GUI 工具包,它还提供了许多其他功能,使开发人员能够更轻松地开发高质量的应用程序。
二.GTK基础函数
1.int main(int argc, char *argv[])
其实这就是程序的主函数入口,不仅在GTK中,在其他很多地方也一样,它其实就等价于int main()。
在C语言中,int main()可以用来定义程序入口点。但是,在使用GTK时,通常需要将命令行参数传递给GTK初始化函数gtk_init(),因此建议使用带参数的int main(int argc, char *argv[])形式。
这样,我们可以通过argc和argv参数访问命令行传递给程序的参数,并在必要时处理它们。例如,可以使用命令行参数来控制程序运行时的某些行为或配置。
总之,尽管在某些情况下可以省略argc和argv参数,但为了更好地使用GTK库,建议保留它们。
2.GtkWidget窗口类型指针
相信我们使用GTK的目的就是为了拜托黑白画图形框的界面,弹出一个窗口。那么我们肯定需要先建立一个窗口类型的变量,GtkWidget提供了这种用法,例如GtkWidget *window是一个指向 GtkWindow 类型对象的指针,它代表了一个GTK窗口。
3.初始化GTK库
gtk_init(&argc, &argv):初始化GTK库,并解析命令行参数。
这就是在初始化整个 GTK+程序,是每一个 GTK+程序必不可少的部分。
4.gtk_window_new()
gtk_window_new()函数是一个在GTK中用于创建新窗口的函数。它返回一个指向新创建GtkWindow对象的指针,该对象代表了一个新的顶级窗口。
以下代码演示如何使用gtk_window_new()函数来创建一个新的顶级窗口:
GtkWidget *window; // 创建一个新的顶级窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
此代码片段创建一个新的顶级窗口,并将其分配给GtkWidget *window指针变量。此时,window指针引用了刚刚创建的新窗口。
在调用gtk_window_new()函数时,可以传递一些参数来设置窗口的类型、标题、大小等属性。例如,GTK_WINDOW_TOPLEVEL参数表示创建一个顶级窗口,而GTK_WINDOW_POPUP参数表示创建一个弹出窗口。我们也可以使用gtk_window_set_title()等其他函数来更改窗口的标题、大小和形状等属性。
该函数有三个参数:
GtkWindowType type:窗口类型,指定窗口的性质。可以是 GTK_WINDOW_TOPLEVEL、GTK_WINDOW_POPUP 或者 GTK_WINDOW_CHILD。
GtkWindow *parent:父窗口,如果不需要指定父窗口,可以传入 NULL。
const gchar *first_property_name:第一个属性名称,可以为 NULL。
其中,第三个参数是可选的,它是一个字符串,表示要设置的第一个属性的名称。如果你想设置更多的属性,可以使用 gtk_widget_set_property() 函数来设置
GTK_WINDOW_TOPLEVEL、GTK_WINDOW_POPUP 和 GTK_WINDOW_CHILD 是 GtkWindowType 枚举类型,表示创建窗口时指定的窗口类型。
GTK_WINDOW_TOPLEVEL:顶层窗口。它是一个独立的窗口,可以包含其他小部件(widget)和控件(widget),并且可以通过桌面管理器进行管理。
GTK_WINDOW_POPUP:弹出式窗口。它通常用于显示一些辅助信息或者用户操作提示,也可以包含其他小部件。
GTK_WINDOW_CHILD:子窗口。它是由其他窗口(例如顶层窗口或弹出式窗口)创建的,通常用作对话框或者消息框等功能性窗口使用。
在使用 gtk_window_new() 函数时,你需要根据自己的需求选择适合的窗口类型。例如,如果你要创建一个全新的应用程序窗口,则应该选择 GTK_WINDOW_TOPLEVEL;如果你要在应用程序中显示一个菜单或者工具提示,则应该选择 GTK_WINDOW_POPUP;而如果你要创建一个对话框或者消息框,则应该选择 GTK_WINDOW_CHILD。
5.gtk_window_set_title()
gtk_window_set_title() 是一个函数,用于设置 GtkWindow 的标题(title)。GtkWindow 是 GTK+ 库中用于创建窗口的控件。
该函数的原型如下:
void gtk_window_set_title (GtkWindow *window, const gchar *title);
其中,window 参数是要设置标题的 GtkWindow 对象指针,title 参数是一个字符串,表示将要设置的标题文本。
在GTK中,窗口是由GtkWidget类派生出来的,而GtkWindow类是GtkWidget的子类。虽然可以将GtkWidget指针强制转换为GtkWindow指针,但是这样做并不安全,因为如果你将错误的类型转换为正确的类型可能会导致程序崩溃或者不可预测的行为。
因此,为了确保代码的正确性和可读性,我们通常会使用提供的宏来确保我们正在处理正确类型的对象。这就是为什么在调用gtk_window_set_title函数时,我们会将窗口参数转换为GtkWindow指针,并使用宏GTK_WINDOW进行类型检查和转换。
6.gtk_widget_show
gtk_widget_show 函数的语法如下:
void gtk_widget_show(GtkWidget *widget);
该函数接收一个指向 GtkWidget 结构体的指针,表示要显示的小部件。该函数没有返回值。
在调用 gtk_widget_show 之后,指定的小部件及其所有子部件将显示在屏幕上。如果该小部件已经显示,则此函数不会有任何效果。
需要注意的是,调用 gtk_widget_show 只会显示该小部件及其子部件,但它并不会自动布局和调整窗口大小。通常,您需要使用其他布局和调整函数来设置小部件的位置和大小,以达到预期的效果。
如果您想要同时显示多个小部件,可以使用 gtk_widget_show_all 函数,它会递归显示指定小部件的所有子部件。
7.gtk_main()
gtk_main()是 GTK+ 库中的一个函数,它会启动 GTK 主循环并等待用户与应用程序进行交互。当用户执行与事件处理相关的操作时,主循环会检查所有挂起的事件,并将它们传递给相应的回调函数进行处理。
通常在创建 GTK 程序时,需要在主函数或其他入口点中调用 gtk_init 函数来初始化 GTK 库,并在其后立即调用 gtk_main 函数以启动主循环。一旦调用了 gtk_main,应用程序就进入事件处理的无限循环状态,直到使用 gtk_main_quit 函数退出主循环。
8.实例代码及解释
#include <gtk/gtk.h> int main(int argc, char *argv[]) { GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Hello World"); gtk_widget_show(window); gtk_main(); return 0; }
#include <gtk/gtk.h>:包含GTK头文件,使我们能够使用GTK库中的函数和类型。
int main(int argc, char *argv[]):定义程序入口点。argc是命令行参数的数量,argv是指向这些参数的指针数组。
GtkWidget *window;:声明一个GtkWidget指针变量window,它将代表我们创建的GTK窗口。
gtk_init(&argc, &argv);:初始化GTK库,并解析命令行参数。
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);:创建一个顶级GTK窗口,并将其分配给window变量。
gtk_window_set_title(GTK_WINDOW(window), "Hello World");:设置窗口标题为“Hello World”。
gtk_widget_show(window);:显示窗口并将其置于屏幕上。
gtk_main();:启动GTK的主循环,等待事件的发生和处理。
return 0;:返回程序的退出状态码,0表示正常退出。
总体来说,这段代码创建了一个顶级GTK窗口,并在其中显示一个标题为“Hello World”的窗口。它展示了如何使用GTK库进行基本的窗口操作。
三.窗口属性设置
1.设置标题
设置窗口标题即gtk_window_set_title()函数,可以看第二部分的进行理解。
2.设置大小
gtk_window_set_default_size函数用于设置窗口的默认大小。该函数定义在GtkWindow类中,函数原型如下:
void gtk_window_set_default_size(GtkWindow *window, gint width, gint height);
该函数接收3个参数:GtkWindow指针、宽度和高度。其中,GtkWindow指针表示要设置默认大小的窗口对象,width和height分别表示窗口的宽度和高度。
使用该函数可以将窗口的默认大小设置为指定的宽度和高度。当用户第一次打开窗口时,窗口会自动调整为该大小。如果用户手动更改了窗口的大小,则下次打开窗口时,窗口将保持上次所选的大小。c
3.设置位置
gtk_window_set_position函数用于设置窗口的显示位置。该函数定义在GtkWindow类中,函数原型如下:
void gtk_window_set_position(GtkWindow *window, GtkWindowPosition position);
该函数接收2个参数:GtkWindow指针和一个枚举类型GtkWindowPosition。其中,GtkWindow指针表示要设置位置的窗口对象,position表示要设置的窗口位置。
GtkWindowPosition是一个枚举类型,它包含以下值:
GTK_WIN_POS_NONE:不更改默认位置。
GTK_WIN_POS_CENTER:居中显示。
GTK_WIN_POS_MOUSE:鼠标所在位置。
GTK_WIN_POS_CENTER_ALWAYS:始终居中显示。
GTK_WIN_POS_CENTER_ON_PARENT:在父窗口上居中显示。
4.关闭窗口
g_signal_connect_swapped() 函数的语法如下:
gulong g_signal_connect_swapped ( gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data );
该函数有四个参数:
instance:要连接信号的对象指针。
detailed_signal:要连接的信号名称,包括详细信息。例如,对于 GTK 窗口 “destroy” 信号,其详细名称是 “destroy::detail”。
c_handler:信号发生时要调用的回调函数指针。(不知道回调函数参考回调函数)
data:传递给回调函数的数据指针。
g_signal_connect_swapped() 函数的第二个参数是要连接的信号的名称,它应该是一个字符串。在 GTK 库中,可以使用 gtk_signal_new() 函数来创建新信号,并将其添加到对象中。
以下是一些常用的 GTK 信号及其含义:
"activate":当用户激活(例如通过单击)控件时发出。
"clicked":当用户单击按钮时发出。
"value-changed":当滑块或调节器的值被更改时发出。
"toggled":用于切换按钮等开关型控件的状态。
"changed":当文本框、文件选择器等控件的内容发生更改时发出。
"destroy":在销毁窗口或其他对象之前发出。
"key-press-event" 和 "key-release-event":当用户按下或释放键盘上的键时发出。
"size-request" 和 "size-allocate":在控件请求空间大小和分配实际大小时发出。
G_OBJECT(window) 是将 window 对象转换为 GObject 类型的指针,以便在 GObject 的生命周期内对其进行操作。这里的 window 可能是一个 GTK 窗口对象。在 GTK 编程中,常使用 G_OBJECT() 宏将窗口对象、按钮对象等控件对象转换为 GObject 类型的指针,并使用 GObject 提供的函数来操作它们。
G_CALLBACK(gtk_main_quit) 是将 gtk_main_quit() 函数转换为回调函数指针,以便在连接信号和回调函数时使用。gtk_main_quit() 是 GTK 库中的一个函数,用于终止主事件循环并退出程序。该函数不接受任何参数,只需要调用它即可让程序安全地退出。在上述代码中,我们使用 G_CALLBACK() 宏将 gtk_main_quit() 函数转换为回调函数指针,并将其作为第三个参数传递给 g_signal_connect_swapped() 函数。
5.增加代码
#include <gtk/gtk.h> int main( int argc, char *argv[]){ GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Center"); gtk_window_set_default_size(GTK_WINDOW(window), 230, 150); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_widget_show(window); g_signal_connect_swapped(G_OBJECT(window), "destroy",G_CALLBACK(gtk_main_quit), NULL); gtk_main(); return 0; }
四.应用程序图标的制作
1.举例
#include <gtk/gtk.h> GdkPixbuf *create_pixbuf(const gchar * filename){ GdkPixbuf *pixbuf; GError *error = NULL; pixbuf = gdk_pixbuf_new_from_file(filename, &error); if(!pixbuf) { fprintf(stderr, "%s\n", error->message); g_error_free(error); } return pixbuf; } int main( int argc, char *argv[]){ GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "icon"); gtk_window_set_default_size(GTK_WINDOW(window), 230, 150); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("web.png")); gtk_widget_show(window); g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL); gtk_main(); return 0; }
上面的就是为一个填加上图标的窗口程序了。
2.gtk_window_set_icon()
gtk_window_set_icon()函数是GTK+库中用于设置顶层窗口图标的函数。它的的语法如下:
void gtk_window_set_icon (GtkWindow *window, GList *list);
其中,window参数是指向要设置图标的顶层窗口的指针,list参数是一个指向包含图标数据的GList链表的指针。该链表中包含了一组GdkPixbuf或GdkSurface等对象,这些对象代表了要设置为窗口图标的图像数据。(一个链表的指针,指向的链表中存的信息是一组GdkPixbuf或GdkSurface等对象)
3.GList
GList 是 GLib 库中的一个链表结构体,用于存储指向任意类型数据的指针,并提供了一系列操作这些指针的函数。它的定义如下:
typedef struct _GList GList; struct _GList { gpointer data; GList *next; GList *prev; };
其中,data 字段是指向任意类型数据的指针,next 和 prev 分别是指向下一个和上一个链表元素的指针。
GLib 提供了一系列函数来创建、销毁和操作 GList 链表。以下是一些常用的函数:
g_list_alloc():分配一个新的 GList 节点。
g_list_append():将一个数据项添加到链表末尾。
g_list_prepend():将一个数据项添加到链表头部。
g_list_insert():将一个数据项插入到链表中指定位置之前。
g_list_remove():从链表中删除一个节点。
g_list_free():释放整个链表的内存。
g_list_length():获取链表的长度。
GList 的一个重要特点是,其可以包含任意类型的数据(通过 gpointer 指针实现),因此非常灵活。在 GTK+ 编程中,经常会使用 GList 来存储窗口组件或者图像等数据。
4.gdk_pixbuf_new_from_file()
gdk_pixbuf_new_from_file()函数的语法如下:
GdkPixbuf* gdk_pixbuf_new_from_file(const char *filename, GError **error);
该函数接受两个参数:
filename: 字符串类型,表示要加载的图像文件的完整路径或相对路径。
error: 指向指针的指针,用于在发生错误时返回一个错误对象。
该函数返回一个GdkPixbuf指针,即已从文件中读取并创建的新图像数据。如果出现错误,则返回NULL并通过error指向的指针传递错误信息
5.错误输出
if(!pixbuf) { fprintf(stderr, "%s\n", error->message); g_error_free(error); }
这段代码的目的是在读取图像文件失败时,将错误信息打印到标准错误流中,并释放用于存储错误信息的内存空间。
首先,如果创建GdkPixbuf对象失败,则gdk_pixbuf_new_from_file()函数返回一个NULL指针。因此,判断!pixbuf是否为真,即可确定是否成功创建了GdkPixbuf对象。
如果没有成功创建GdkPixbuf对象,那么相应的错误信息会存储在GError类型的对象中。使用error->message语句可以获取包含错误信息的字符串,fprintf()函数将其格式化并输出到标准错误流中(通常是控制台或日志文件)。
最后,使用g_error_free()函数释放用于存储错误信息的内存空间,这样可以避免内存泄漏。
6.自定义函数功能
函数 create_pixbuf() 作用是从一个 png 图象文件中生成 GdkPixbuf 类型数据。
五.Linux下部署GTK环境
在Linux下部署GTK环境,您需要完成以下几个步骤:
- 安装GTK库
在终端中执行以下命令来安装GTK库:
sudo apt-get install libgtk2.0-dev
编译GTK程序
使用以下命令编译GTK程序:
gcc -o your_program `pkg-config --cflags gtk+-2.0` your_program.c `pkg-config --libs gtk+-2.0`
这条命令将会将your_program.c文件编译成一个可执行文件并链接到GTK库。
- 运行GTK程序
运行已编译的GTK程序,可以通过以下命令:
./your_program
如果一切顺利,您应该能够看到您编写的GTK程序在屏幕上运行了。
六.说明
本篇博客的例子实在Windows下GTK2.0环境下实现的,GTK最新已达到4.0版本了,新版本中抛弃了很多GTK以前版本的语法,如果你在4.0环境下进行上述操作,可能会报错,注意环境哦。