GTK+学习:不仅仅是Hello world!

简介:
一般在学习一项新技术的时候,我最希望看到的不是那一本本厚厚的理论书籍或者编程技巧,即便没有什么技巧,我希望的是能够看到我的成果,即便只是一个小小的什么都不能做的窗口,也能满足一下我的好奇心。所以,现在我们先来写一个小程序,看看GTK+程序是怎样编写的。
 
由于上次我们已经配置好了编译环境,所以,直接打开你所喜爱的IDE或者记事本,敲下如下的代码。这里我是在Windows平台下使用VS2005编译的,有些术语在其他平台下可能会有出入,但整体是类似的。
 
InBlock.gif#include <gtk/gtk.h> 
InBlock.gif 
InBlock.gif int main( int argc,  char** argv) 
InBlock.gif
InBlock.gif  GtkWidget* window; 
InBlock.gif  gtk_init(&argc, &argv); 
InBlock.gif  window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
InBlock.gif  gtk_widget_show(window); 
InBlock.gif  gtk_main(); 
InBlock.gif   return 0; 
InBlock.gif}
 
然后进行编译连接,运行之后,如果没有错误的话,将会出现一个小窗口。嗯,这就是我们用GTK+编写的界面了。
 
下面来看看这段程序。首先第一行,是引用的头文件,一般来说只要引用这个gtk.h就可以了。按照前面所述的方法引入include文件的话,就是在gtk目录下的gtk.h了。
 
然后是main函数定义,和C语言一模一样。
 
main函数中,第一句声明一个GtkWidget的指针。前面说过,GTK+是按照面向对象思想设计的,不妨把这个GtkWidget当作类吧,虽然C编译器并不这么认为。然后是gtk_init调用,这是初始化GTK+环境。写过OpenGL程序的朋友应该比较清楚,OpenGL里面也有一个类似的init函数。然后对前面声明的指针赋值。看看这个函数名字:gtk_window_new,很清楚是新建一个window指针。按照面向对象的写法就是:
        GtkWidget* window = new GtkWindow(GTK_WINDOW_TOPLEVEL);
 
怎么样?清楚很多了吧?其实这里就已经暗示出了,GtkWindow继承了GtkWidget类。这些在后面就会看出,GtkWidget其实是所有控件的父类。传递的参数是GTK_WINDOW_TOPLEVEL,指明是一个顶层的窗口。然后使用gtk_widget_show设置显示,同样把它想象成面向对象的语法就是:
        window -> show();
 
最后一句gtk_main,将我们的程序带入GTK+的事件监听循环。
 
这样,我们的程序就介绍完了。但是也许就会发现一个问题:怎么后面还有一个黑黑的控制台窗口啊?这是因为默认运行方式是Debug,换成Release看看?那个丑丑的窗口没有了吧?而且生成的二进制文件也比那个小了很多。
 
嗯,当我们按下关闭按钮时,窗口是不见了,但是程序并没有退出啊?对哦,因为我们没有添加事件监听啊,所以当关闭窗口的时候,GTK+也不知道该怎么做。所以,我们继续修改代码如下:
 
InBlock.gif#include <gtk/gtk.h> 
InBlock.gif 
InBlock.gif int main( int argc,  char** argv) 
InBlock.gif
InBlock.gif  GtkWidget* window; 
InBlock.gif  gtk_init(&argc, &argv); 
InBlock.gif  window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
InBlock.gif  g_signal_connect(GTK_OBJECT(window),  "destroy", G_CALLBACK(gtk_main_quit), NULL); 
InBlock.gif  gtk_widget_show(window); 
InBlock.gif  gtk_main(); 
InBlock.gif   return 0; 
InBlock.gif}
 
注意,我们添加了一个事件监听函数:
g_signal_connect(GTK_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
它的意思是,对于对象window,当"destroy"时间发生时,调用gtk_main_quit函数,传给这个函数的参数是NULL。如果我们使用Java语言的事件监听写法,就是这样子的:
window.addDestroyListener(new CallbackFunc(){
    gtk_main_quit();
});
 
不过这段代码应该也是比较容易读懂的。其实这就是GTK+中添加事件监听的写法,每个控件的每个事件监听都是这样编写代码,很统一。修改完成后运行一下,点下关闭按钮:哈,程序退出了!
 
那么,我们再来修改一下程序吧:
 
InBlock.gif#include <gtk/gtk.h> 
InBlock.gif 
InBlock.gif int main( int argc,  char** argv) 
InBlock.gif
InBlock.gif  GtkWidget* window; 
InBlock.gif  gtk_init(&argc, &argv); 
InBlock.gif  window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
InBlock.gif  gtk_window_set_title(GTK_WINDOW(window),  "Hello world!"); 
InBlock.gif  g_signal_connect(GTK_OBJECT(window),  "destroy", G_CALLBACK(gtk_main_quit), NULL); 
InBlock.gif  gtk_widget_show(window); 
InBlock.gif  gtk_main(); 
InBlock.gif   return 0; 
InBlock.gif}
 
运行一下看看?窗口标题已经换成了经典的Hello world!了。
 
读一下代码,我们添加了这么一句:
gtk_window_set_title(GTK_WINDOW(window), "Hello world!");
 
如果你能想到它的面向对象语法,就达到目的了啊:
((GtkWindow*)window) -> setTitle("Hello world!");
 
注意,因为C编译器是不理解面向对象的多态机制的,所以,GTK+使用了很多宏来进行类型转换,比如这里的GTK_WINDOW。还记得我们声明的是GtkWidget指针,需要转换成GtkWindow指针才能使用set_title函数的。同时,这个宏也有类型检测的功能,如果不能转换,是会抛出异常的。
 
好了,现在经过一步步的代码添加,我们已经了解了GTK+程序的编写过程,并且能够创建一个窗体,添加事件监听和修改控件属性——GUI编程的主体不就是这些吗?剩下的就是一些细节,和对于庞大的控件库的学习了。


本文转自 FinderCheng 51CTO博客,原文链接:

http://blog.51cto.com/devbean/108758
相关文章
|
4月前
|
数据可视化
【Qt】—— Hello World程序的实现
【Qt】—— Hello World程序的实现
|
小程序 程序员 Python
Python|GUI编程Button组件介绍
Python|GUI编程Button组件介绍
286 1
|
存储 XML 安全
GTK入门
GTK入门
288 0
|
PHP
php扩展开发一:hello world
php扩展开发一:hello world
104 0
|
Linux Shell C语言
Linux下gcc编译时出现In function `_start‘:(.text+0x**) :解决方案
Linux下gcc编译时出现In function `_start‘:(.text+0x**) :解决方案
502 0
|
Ubuntu IDE Linux
Linux-Qt Quick学习1-Hello world
Qt作为共平台的开发IDE。实在是强大,在Quick的学习中,与平台无关,我这里使用ubuntu和openSUSE,之所以不用Windows,是因为我想借这个机会过学习一点linux的东西,哪怕是熟悉一下简单的命令也好,
152 0
Linux-Qt Quick学习1-Hello world
|
Python
VSCode 配置快速输入Python的Main函数方法
VSCode 配置快速输入Python的Main函数方法
2305 0
VSCode 配置快速输入Python的Main函数方法
|
测试技术 数据安全/隐私保护 Python
python的argpare和click模块详解
python的argpare和click模块详解一、argparse模块1、模块说明12 argparse是python的标准库中用来解析命令行参数的模块,用来替代已经过时的optparse模块,argparse能够根据程序中的定义的sys.
1242 0