第十六章 用GTK+进行GNOME编程

Linux 中所有的 GUI 库都基于被称作X视窗系统的底层视窗系统。

在编写本章节的代码时,需要安装好相应的库。


X视窗系统简介

X是一个开源的图形化系统。X没有定义用户界面,但提供了创建用户界面的手段。这意味这可以自由地创建自己的整个桌面环境。

两个桌面项目逐渐浮现成为了 Linux 用户的最爱: GNOME 和 KDE 。

X视窗系统被分别称为硬件级和应用程序级组件,它们分别被称为X服务器和X客户端。这些组件使用X协议进行通信。

X服务器

X服务器运行在用户的本地机器上,它在屏幕上完成低层的绘图操作。X服务器直接与显卡交互。

X服务器通过鼠标和键盘监听用户输入,并将键盘按键和鼠标点击传输给X客户端应用程序。这些信息被称为事件( event )。

X客户端

X客户端是以X视窗系统作为 GUI 的任何程序。例如 xterm 。通常情况下,X客户端等候X服务器传送用户事件,然后通过给X服务器发送重绘消息来响应,

X协议

X客户端和X服务器使用X协议进行通信,这使得客户端和服务器可以通过网络分离。对于绝大多数个人 Linux 系统来说,X客户端和X服务器都运行在同一个系统上。

Xlib库

Xlib 库是X客户端间接用于产生X协议消息的库。它提供一个非常底层的 API 供客户端在X服务器上绘制非常基本的元素,并响应最简单的输入。

GUI程序员应该使用X工具包,这比使用 Xlib 要简单方便。

X工具包

是一个GUI库,X客户端可以利用它来极大地简化窗口、菜单和按钮等的创建。诸如此类的 GUI 元素被称为 widget 。

最流行的工具包现在是 GTK+ 和 QT 。它们分别构成了 GNOME 和 KDE 桌面的基础。

窗口管理器

窗口管理器负责定位屏幕上的窗口。它还负责装饰每个窗口,通常由一个框架和一个带有最大化、最小化和关闭图标的标题栏组成。

创建GUI的其他方法——平台无关的窗口API

比如使用 JAVA, C#, PYTHON 等。

GTK+简介

GTK+是一个函数库,它提供了一组已经制作好的组件。

GTK+完全是用C语言编写的,而且绝大多数GTK+软件也是用C语言编写的。许多语言绑定使你可以在其他语言中使用GTK+ ,比如 C++ , Python , PHP 等。

GLib 类型系统

GTK+ 中,有许多以字母g开头的C语言数据类型,如 gint, gchar, gshort 。这是为了跨平台开发。

GLib 和 GObject 提供了一组数据类型、函数和宏的标准替代集来进行内存管理和处理常见任务,从而实现跨平台开发。

GTK+对象系统

尽管 GTK+ 是完全用C语言编写的,但是它通过 GObject 库支持对象和面向对象编程。这个库通过宏来支持对象继承和多态。

为了方便,所有 Widget 的创建函数都返回一个GtkWidget 的类型。例如:

GtkWdiget* gtk_window_new(GtkWindowType type);

可以通过专用的宏实现继承关系间的类型转化:

// 把 GtkWidget* 转化成了一个 GtkContainer*
gtk_container_add(GTK_CONTAINER(window), awidget);

GNOME 简介

GNOME 的目的是为 Linux 创建一个统一的桌面。

现在它已经成为 Fedora, Red Hat, Ubuntu 以及 openSUSE 等发行版默认 Linux 桌面的基础。

安装 GNOME/GTK+ 开发库

书中介绍了一些方法。

在我使用的 CentOS7 下面,使用这样的命令安装:

$ sudo yum -y install gtk2.x86_64
$ sudo yum -y install gtk2-devel.x86_64
$ sudo yum -y install gtk2-engines.x86_64
$ sudo yum -y install libgnome.x86_64
$ sudo yum -y install libgnome-devel.x86_64
$ sudo yum -y install libgnomeui.x86_64
$ sudo yum -y install libgnomeui-devel.x86_64

可以运行 GTK+ 的演示程序,它还包含了代码:

$ gtk-demo

使用这样的命令来生成编译选项构建 gtk+ 程序:

`pkg-config --cflags --libs gtk+-2.0`

gtk_window_new 可以创建一个窗口。

一个 gtk 程序的简单框架是:

#include <gtk/gtk.h>

static Widget *window;

int main(int argc, char* argv[])
{
    gtk_init(&argc, &argv); // 初始化 GTK+ 库,必须在调用任何 GTK 函数之前调用

    // 给窗口添加内容

    gtk_widget_show_all(window); // 显示实际窗口和其内容
    gtk_main(); // 把控制权交给 GTK+ 来启动交互过程,并且一直运行,直到调用 gtk_main_quit 才返回
    return 0;
}

事件、信号和回调函数

所有的 GUI 库都有一个共同点:必须存在某种机制来响应用户动作并执行相应代码。

现代窗口系统用事件和事件监听系统来处理这个问题。其思想是,每次用户输入都触发一个事件。程序员需要编写监听这些事件的代码,以及当事件被触发时要执行的代码。

GTK+ 有自己的事件和监听器系统,它们被称为信号和回调函数。

回调函数的原型如:

void a_callback(GtkWidget *widget, gpointer user_data);

连接回调函数的方法是 g_signal_connect。

组装盒构件

GUI 的布局对其可以用性来说至关重要。排列构件的真正困难在于,你不能指望所有用户都有相同的屏幕分辨率,或者有相同的窗口大小、主题、字体、颜色方案。

为了保持一致,要避免使用绝对坐标来放置构件,而是采用一种更灵活的布局系统。 GTK+ 通过容器构件来实现这一目标。盒构件是一个非常有用的容器构件类型。

盒是一个不可见的构件,其工作就是包含其他的构件,并控制它们的布局。

使用 gtk_hbox_new 和 gtk_vbox_new 来创建一个横向和纵向的盒构件。

使用 gtk_box_pack_start 或 gtk_box_pack_end 来向盒构件添加构件。

Gtk+构件

本节介绍了 GtkWindow, GtkEntry, GtkSpinButton, GtkButton, GtkCheckButton, GtkToggleButton, GtkRadioButton, GtkTreeView 的相关 API 。

GNOME 构件

GTK+ 被设计成独立于桌面的。它不假定运行在 GNOME 中,甚至不假定它运行在 Linux 上。这样, GTK+ 可以被相对容易地移植到 Windows 或者任何其他视窗系统中。但其导致的结果是: GTK+ 缺乏将程序与桌面紧密结合的方法。

GNOME 库包含 GNOME 构件,它们扩展了 GTK+ ,用一些更容易使用的构件替换了 GTK+ 中的部分构件。

略去后续繁杂的内容。