Feb 19

一、简介

GTK+ 是一套跨平台的图形用户界面(Graphical User Interface)开发工具包,按 LGPL 许可协议发布的。虽然最初是为 GIMP(GNU Image Manipulation Program) 写的,但早已发展为一个功能强大、设计灵活的通用图形库。特别是在 GTK+ 被 Linux 桌面项目 GNOME 选中使得它广为流传,成为 Linux 下开发图形用户界面应用程序的主流开发工具之一。当然 GTK+ 应用程序开发与运行并不要求必须在 Linux 上,事实上,GTK+ 早已经被成功地移植到了 Mac OS X 以及 MS Windows 上。在开发早期的 GIMP 版本时,Peter Mattis 和 Spencer Kimball 创建了 GTK(GIMP Toolkit) 工具包,作为 Motif 工具包的替代,后者在那个时候不是免费的。当 GTK 开发工具包获得了面向对象特性和可扩展性之后,才在名称后面追加上了符号 "+",也即 GTK+。

二、GCC 工具链

GCC(GNU Compiler Collections) 是 Linux 系统中默认的开发工具、Autotools 是 Linux 中开发大型项目管理工具。Red Hat 系中这些开发工具的安装可执行

$ sudo dnf install "Development Tools"

Debian 系可执行

$ sudo apt-get install build-essential

Gentoo 由于本身的理念就是编译所有的包,因此系统已经自带了 GCC 工具链,无须额外安装其他 GCC 开发工具。

三、C/C++ 的手册页

在编程的过程中有时会记不得某个函数的用法,此时查找手册页是比较快的。为了能够用命令行 man 查看 C/C++ 的函数,需要安装相关的手册页及其工具。在 Red Hat 系中执行

$ sudo dnf install man-pages libstdc++-docs

Debian 系可执行

$ sudo apt-get install manpages-dev manpages-posix manpages-posix-dev glibc-doc libstdc++6-4.3-doc

Gentoo 中安装稍微麻烦一点,可执行

$ sudo sh -c 'echo "sys-devel/gcc doc cxx " >> /etc/portage/package.use'
$ sudo emerge -av1 gcc
$ sudo emerge -av man-pages man-pages-posix

手册页的索引由 mandb 命令管理,有时在安装了新的手册页后,可能需要更新一下索引才能用 man kman f 查询到函数,也即

$ mandb c

然后就可以查看这些文档了。比如,查看 fopen 的手册页:

$ man fopen

四、GTK+ 库的概述

GTK+ 是基于以下库开发的:

  • glib:GTK+ 与 GNOME 的底层核心库,主要提供了 C 数据结构、可移植封装、运行时功能接口,譬如事件循环、多线程、动态装载和对象机制等。换而言之,Glib 是 GTK+ 能够“面向对象”的基础。GTK+ 中与界面无关的底层部分基本都被并入 glib。GLib 库还进一步分离成 GIO、GObject 等库。GIO 专门处理输入输出流。而 GObject 则维护着 GTK+ 所使用的一套对象系统。正是 GObject 提供的面向对象的机制,使得 GTK+ 可绑定很多种开发语言,例如 C++、Python、Perl、Java、C#、PHP 等其他高级语言。
  • pango:国际化文本陈列及渲染库,它是 GTK+ 的文本与字体处理核心;
  • atk:可访问接口库,它可以让 GTK+ 程序很方便地使用屏幕阅读器、放大镜以及一些输入设备等;
  • cairo:过去 cario 被称为 Xr 或 Xr/Xc,它是一个跨平台的开放源代码的矢量图形函数库,可以提供高质量的显示和打印输出。通过 Glitz 函数库, Cairo 能使用 OpenGL 或 X Render 扩展的硬件加速功能来绘制图像,这基于 Cairo 的应用能在现代化的 3D 显示硬件上获得益处。
  • gdk-pixbuf:GDK(GDK 是 GTK+ 从窗口系统细节中提取出来的一组接口,可以直接访问窗口细节。实际上,GDK 是 GTK+ 用户界面图形库提供的一些底层“图形实现”和“窗口实现”的方法,在 Linux 中,GDK 是对 Xlib 库提供接口的封装。)的一个部分,提供了一组位图函数,包括位图变换、位图文件读写等等,用于加载图像和维护图像“缓存”的(pixel buffer)。

要装 GTK+,先安装这写库,当然它们又依赖其它一些库,在 Linux 系统中可完全交由 Linux 的包管理器处理。还有一些库是 GTK+ 运行依赖的,下面是几个重要的:

  • gettext:它是国际化库,主要用于制作多语言程序。运行时 gettext 自动识别操作系统语言,然后从已有语言包中选择一个最合适用户的语言。当操作系统上没有 gettext() 函数的时候需要安装它。
  • libiconv:它是字符集转换库,通常操作系统上没有提供 iconv() 函数的时候才会安装它。GTK+ 内部使用 UTF-8 字符集,有时需要字符集转换。
  • freetype:它是一个操作字体的函数库,不但可以处理点阵字体,也可以处理多种矢量字体,包括 truetype 字体,为上层应用程序提供了一个统一的调用接口。
  • fontconfig:它提供系统范围内字体设置、定制和允许应用程序访问的函数库。实际上,GTK+ 的字体绘制是通过 pango、freetype 与 fontconfig 三者协作来完成的。其中,fontconfig 负责字体的管理和配置,freetype 负责单个字符的绘制,pango 则完成对文字的排版布局。
  • libjpeg:它提供了 JPEG 算法压缩文件图形文件供 GTK+ 程序读写 JPEG 格式的图形文件;
  • libtiff:它是用操作 TIFF 格式(标记图象文件格式)的图形文件并为 GTK+ 程序读写 TIFF 格式的图形文件的库;
  • libpng:它是用来创建与操作 PNG 格式的图形文件并为 GTK+ 程序提供读写 PNG 文件的库。PNG 格式的图形文件是被设计来替代 GIF 格式的,它对于更小范围的 TIFF 格式是来说,有了很多的进步和拓展并且减少了关于专利权的麻烦。

五、GTK+ 的 C 开发包

目前,GTK+ 开发包有三个版本:GTK+ 1、GTK+ 2 与 GTK+ 3,在 Linux 系统上是可以共存的,但由它们开发的程序需要对应的 GTK+ 开发包才能正常编译与运行。现在 GTK+ 2 是主流,但都在向 GTK+ 3 过度。根据自己的需要选择 GTK+ 版本,这里就以 GTK+ 2 为例。安装 GTK+ 开发环境,在 Red Hat 系中执行

$ sudo dnf install gtk2-devel gtk2-devel-docs

Debian 系可执行

$ sudo apt-get install libgtk2.0-dev libgtk2.0-doc

Gentoo 中执行

$ sudo sh -c 'echo "x11-libs/gdk-pixbuf doc \
                    dev-libs/glib doc \
                    x11-libs/pango doc \
                    x11-libs/cairo doc \
                    dev-libs/atk doc \
                    x11-libs/gtk+ doc" >> /etc/portage/package.use'
$ sudo emerge -av gtk+

若在开发过程中需整合 GNOME 环境,在 Red Hat 系中执行

$ sudo dnf install libgnome-devel gnome-devel-docs

Debian 系可执行

$ sudo apt-get install gnome-devel gnome-devel-docs

Gentoo 中执行

$ sudo emerge -av gnome-devel-docs

六、GTK+ 应用程序接口文档查看器

在 GNOME 桌面中,查看 GTK+ 应用程序接口文档的查看器是 DevHelp。安装它的方法很简单,在 Red Hat 系中执行

$ sudo dnf install devhelp

Debian 系可执行

$ sudo apt-get install devhelp

Gentoo 中执行

$ sudo emerge -av devhelp

通常,这些 API 文档会随着开发工具包的安装会被放入 /usr/share/gtk-doc/ 目录下。有了 DevHelp,查看它们非常容易,只需要在应用程序列表中点击 Devhelp 图标,或者在终端模拟器中执行

$ devhelp

八、pkg-config 的安装与使用

pkg-config 是编译器的辅助工具,可以帮助 GCC 找到所需要的头文件与库文件路径。它的安装非常简单。在 Red Hat 系中执行

$ sudo dnf install pkg-config

Debian 系可执行

$ sudo apt-get install pkg-config

Gentoo 中执行

$ sudo emerge -av dev-util/pkgconfig

现在试试 pkg-config,先查看 Linux 系统中是否安装 glib 库:

$ pkg-config --list-all | grep -i glib

若已安装,例如 glib-2.0,接着查看一下所安装的 glib 的具体版本:

$ pkg-config --modversion glib-2.0

再来列出 GCC 所需要的 glib-2.0 头文件所在目录

$ pkg-config --cflags glib-2.0

接着列出 GCC 所需要的 glib-2.0 库文件所在目录

$ pkg-config --libs glib-2.0

当然 pkg-config 无法智能到无所不知的地步,它是通过存放在标准目录 /usr/lib/pkgconfig 下的 .pc 文件来查找 GCC 所需头文件与库文件路径的。当然,也可以通过设置环境变量 PKG_CONFIG_PATH 让 pkg-config 找到非标准目录下的 .pc 文件,在这些文件里同样记录了 GCC 所需要的头文件和库文件所在的路径。例如

$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

另外,值得提到一下 GTK+ 1 自带的工具 gtk-config,它与 pkg-config 的运作机制相像,但显然已被 pkg-config 取代。

九、GTK+ 的基本概念与约定

首先来解释 GTK+ 中几个基本的概念,以方便将来的分析。

  • 物件(GtkWidget):GTK+ 中每一个窗口里的组成要素都被视为一个物件,如按钮、文本等等,窗口本身也是一个物件。总之 GTK+ 的界面就是由物件构成的。注意,物件都使用指针来管理,物件外在表现就是一个特定类型的指针。
  • 容器(GtkContainer):物件里的一大类,容器的特点是其内部能够容纳其他物件。容器最基本的功能之一是将各种物件良好地组织起来。 GTK+ 的容器能在大小改变时自动调整内含物件的大小,这使得 GTK+ 能够很智能地相应窗口或其他物件的大小改变。这为我们提供了很大的方便,往往我们不需要指定某个物件的大小,只需说明他所在的容器位置, GTK+ 会把物件的实际位置和大小自动计算出来。
  • 继承、组合:虽然是 C 语言写的,但 GTK+ 灵活地运用了面向对象思想。 GTK+ 的物件体系中就有继承、组合这样的关系,如窗口(GtkWindow)是由容器(GtkContainer)派生出来的。
  • 类型转换宏:C 语言本身没有“继承”这个概念,那么,如果把派生的物件直接当做基物件使用,会出现一个编译警告,即“隐式指针类型转换”,但不会出错。为了消除这个警告,需要做指针类型转换。一般情况下类型转换使用类型转换宏。类型转换宏内部会检查物件的继承关系,确定能否进行转换,然后再做显式类型转换。
  • 事件(event):用户的操作,比如按下某个按钮或快捷键,被视为一个事件。
  • 信号(signal):GTK+ 是基于信号回调(signal-slot)机制的。信号捆绑了一个事件和一个函数,在用户触发这个事件时,这个函数会被调用一次。从这个角度来说, GTK+ 是基于物件的,即程序围绕物件属性、事件、方法进行。
  • 主循环(main loop):GTK+ 程序在一个主循环中运行。当一个事件被触发时,它将被插入队列中;在主循环中被触发的事件会被逐个处理(和这个事件绑定的函数被逐个调用);没有事件被触发时,程序就处于等待状态,等待下一个事件被用户触发。直到退出主循环的函数被调用,GTK+ 程序才结束。

GTK+ 拥有开源软件的很多特点,比如结构高度严谨、可读性甚好。现在介绍一下 GTK+ 的关键字命名方式也即 GTK+ 命名规范,以便阅读一段 GTK+ 程序。

  • 普通变量类型名:全小写写法。其中以 "g" 开头属于 GLib 库,如 "gint";
  • 物件类型名:驼峰写法(首字母大写),以 "Gtk" 开头,形如 "GtkWindow"。在 GTK+ 内部,类型是像下面这样定义的(以 GtkWindow 为例)。
    typedef _GtkWindow GtkWindow
  • 函数名:小写夹下划线写法,以 "gtk_"、"g_" 为前缀,形如 "gtk_main()"、"g_print()"。如果是针对某类物件的函数,则前缀中还有物件类型名,形如 "gtk_window_new()"。
  • 常量名:大写夹下划线写法,以 "GTK_" 为前缀,形如 "GTK_WINDOW_TOPLEVEL"。
  • 类型转换宏:大写夹下划线写法,以 "GTK_" 为前缀。一般来说,宏名字和类型名相仿,比如要把 GtkWindow* 类型的物件转换为 GtkContainer* 类型,就使用宏 "GTK_CONTAINER()"。

GTK+ 本身只负责界面组织,它提供的函数大致可分为三类,物件(Widget)、对象(Object)和其它工具函数。物件就不多说了,GTK+ 中的对象是一些功能更加复杂的不可见元素,它们和界面息息相关,比如 GtkBuilder。工具函数提供一些与界面关系密切的实用功能,比如剪贴板读写。

十、GTK+ 开发环境的简单测试

GTK+ 安装完成后,做个测试程序,代码如下

$ cat hellogtk.c

#include <gtk/gtk.h>

void hello(GtkWidget *widget,gpointer data)
{
    g_print("Hello GTK+!\n");
}

gint delete_event(GtkWidget *widget,GdkEvent *event,gpointer data)
{
    g_print ("delete event occurred\n");
    return(TRUE);
}

void destroy(GtkWidget *widget,gpointer data)
{
    gtk_main_quit();
}

int main( int argc, char *argv[] )
{
    GtkWidget *window;
    GtkWidget *button;
    gtk_init (&argc, &argv);
    window=gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_signal_connect (GTK_OBJECT(window),"delete_event",GTK_SIGNAL_FUNC(delete_event),NULL);
    gtk_signal_connect (GTK_OBJECT (window), "destroy",GTK_SIGNAL_FUNC (destroy), NULL);
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
    button = gtk_button_new_with_label ("Hello Ubuntu!");
    gtk_signal_connect (GTK_OBJECT (button), "clicked",GTK_SIGNAL_FUNC (hello), NULL);
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                                 GTK_SIGNAL_FUNC(gtk_widget_destroy),GTK_OBJECT (window));
    gtk_container_add (GTK_CONTAINER (window), button);
    gtk_widget_show (button);
    gtk_widget_show (window);   /*显示一个窗口*/
    gtk_main();   /*进入主循环*/
    return(0);
}

用下面命令编译运行

$ gcc hellogtk.c -o hellogtk `pkgconfig --cflags --libs gtk+2.0`
$ ./hellogtk

会显示带有一个按钮的窗口,点击按钮以后窗口关闭,命令行显示 Hello GTK+!

十一、安装 GTK+ 界面快速设计工具

Glade 是 GTK+ 的界面辅助设计工具,可以通过拖放控件的方式快速设计出用户界面,这样的优势在于在设计的同时能直观地看到界面上的控件,并且可以随时调整界面上的设计。用 Glade 设计的图形用户界面是以 XML 格式的文件保存,它描述了控件的结构、每个控件的属性。用户可以动态加载这个界面文件。而且,界面和程序逻辑是完全分离,用户修改了界面,也不需要重新编译程序。Glade 有三个版本:基于 GTK+ 1 版本的 Glade、基于 GTK+ 2 及之后版本的 Glade2、Glade3。一般推荐使用 Glade3 设计 GTK+ 程序界面。

Glade 的布局文件有 2 种格式: Libglade、GtkBuilder。由于布局文件格式的不一样,最终使用的库函数不一样。选择 GtkBuilder 直接生成 XML 格式文件,但是后缀名仍是 .glade。如果选择 Libglade,可通过下述命令行

$ gtk-builder-convert

将它装换为 XML 格式文件。总的来说,推荐使用 GtkBuilder 格式的布局文件。

Glade 的安装很容易,不要要记住,若要使用 Libglade 格式的布局文件,需要安装 libglade 库。在 Red Hat 系中执行

$ sudo dnf install glade3 libglade2-devel

Debian 系可执行

$ sudo apt-get install glade libglade2-dev

Gentoo 中执行

$ sudo sh -c 'echo "dev-util/glade doc" >> /etc/portage/package.use'
$ sudo emerge -av dev-util/glade libglade

安装完成后,在应用程序列表中点击 Devhelp 图标,或者在终端模拟器中执行

$ glade

即可启动 Glade 工具。

1)Glade 画 UI,注意保存为 Libglade 格式,然后在下述 C 代码中使用该布局文件

$ cat libgladedemo.c

#include <glade/glade.h>
#include <gtk/gtk.h>

/**
 * 假设布局文件定义了一个名为 button1 的按钮,并且其 clicked 信号处理函数如下
 * 若是在 MS Windows 中,回调函数要加上修饰词 G_MODULE_EXPORT,也即
 */
/* G_MODULE_EXPORT */
void on_button1_clicked(GtkWidget* widget,gpointer data)
{
    g_print("hello, world!\n\r");
}

int main(int argc,char **argv)
{
    /* Libglade 类型,用于布局 */
    GladeXML *gxml;
    GtkWidget *window;
    gtk_init(&argc,&argv);

    /* 下面开始通过文件获取布局信息了 */
    gxml=glade_xml_new("glade.glade",NULL,NULL);
    /* 信号连接 */
    glade_xml_signal_autoconnect(gxml);

    /* 获取构件 */
    window=glade_xml_get_widget(gxml,"window1");  /* window1 是 glade3 中窗口的名字*/
    button = glade_xml_get_widget(gxml,"button1");  /* button1 是 glade3 中按钮的名字*/

    gtk_widget_show(window);
    gtk_main();
    return 0;
}

在编译代码时,加上 libglade-2.0,如:

$ gcc libgladedemo.c -o libgladedemo `pkg-config --cflags --libs gtk+-2.0 libglade-2.0`
$ ./libgladedemo

2)Glade 画 UI,注意保存为 GtkBuilder 格式,同样在 C 代码中使用该布局文件

$ cat gtkbuilderdemo.c

#include <gtk/gtk.h>

/**
 * 假设布局文件定义了一个名为 button1 的按钮,并且其 clicked 信号处理函数如下
 * 若是在 MS Windows 中,回调函数要加上修饰词 G_MODULE_EXPORT,也即
 */
/* G_MODULE_EXPORT */
void on_button1_clicked(GtkWidget* widget,gpointer data)
{
    g_print("Hello World !\r\n");
}

int main (int argc, char **argv)
{
    /* GtkBuilder 类型,用于布局 */
    GtkBuilder *gtkBuilder;
    GtkWidget *mainwin;
    /* Initialize the widget set */
    gtk_init (&argc, &argv);
    /* Create the main window */
    /* 通过 main.glade 建立布局 */
    gtkBuilder= gtk_builder_new();
    gtk_builder_add_from_file(gtkBuilder,"main.glade",NULL);

    /* 连接信号,信号名在布局文件中定义 */
    gtk_builder_connect_signals (gtkBuilder, NULL);

    /* 通过布局文件获得构件,此处为一个对话框型的窗体 */
    mainwin= GTK_WIDGET(gtk_builder_get_object(gtkBuilder,"dialog1"));
    button = GTK_WIDGET(gtk_builder_get_object (builder, "button1"));
    g_object_unref ( G_OBJECT(gtkBuilder) );
    /* Show the application window */
    gtk_widget_show_all ( mainwin );
    /* Enter the main event loop, and wait for user interaction */
    gtk_main ();
    /* The user lost interest */

    return 0;
}

在编译代码时,无须增加额外库,也即:

$ gcc gtkbuilderdemo.c -o gtkbuilderdemo `pkg-config --cflags --libs gtk+-2.0`
$ ./gtkbuilderdemo

十二、GTK+ 的其他语言开发包

将 GTK+ 与 C 语言的近亲 C++ 绑定,便是 GTKmm。Glade 还是 GTKmm 的界面快速构建工具,推荐使用 Glade3。若使用 libglade 格式的界面布局文件,需额外安装相应的库。在 Red Hat 系中执行

$ sudo dnf install gtkmm24-devel gtkmm24-docs libglademm24-devel

Debian 系可执行

$ sudo apt-get install libgtkmm-2.4-dev libgtkmm-2.4-doc libglademm-2.4-dev libglademm-2.4-doc

Gentoo 中执行

$ sudo sh -c 'echo "dev-cpp/libsigc++ \
                    dev-cpp/glibmm doc \
                    dev-cpp/pangomm doc \
                    dev-cpp/cairomm doc \
                    dev-cpp/atkmm doc \
                    dev-cpp/gtkmm doc \
                    dev-cpp/libglademm doc" >> /etc/portage/package.use'
$ sudo emerge -av gtkmm libglademm

测试一下 GTKmm 开发环境,下面是一个简单 Hello GTKmm 的例子

$ cat hellogtkmm.cpp

#include <gtkmm.h>
#include <libglademm/xml.h>         /* 访问Glade文件所需的头文件 */
#include <iostream>                  /* 输出错误信息到控制台 */
#include <assert.h>                  /* assert()断言 */
 
using namespace Gnome::Glade;
 
class HelloApp: public Gtk::Main {    /* 继承“Gtk::Main”类 */
public:
    HelloApp(int argc, char *argv[]):
        Gtk::Main(argc,argv),             /* 必须在初始化列表中调用父类的构造函数 */
        main_window(0)                     /* 为主窗口的指针赋初值 */
    {
        try
        {
            /* 从同目录下的GLADE文件创建“Gnome::Glade::Xml”对象 */
            ref_xml = Xml::create("helloapp.glade");
        }
        catch(const XmlError& ex)
        {
            /*   出错时错误信息输出到控制台,并返回 */
            std::cerr << ex.what() << std::endl;
            return;
        }
   
        /*
          取得主窗口的指针,存入main_window变量中,并确保成功。
          main_window为0值表示失败,多是因为指定的控件名称不正确或不存在。
          第一个参数就是Glade文件中定义的控件名称,是字符串型。
        */
        ref_xml->get_widget("main_window", main_window);
        assert(main_window);
    }
 
    ~HelloApp()
    {
        /* 由于采用了智能指针,我们不需要管理资源的释放 */
    }
 
    show_window()
    {
        /*
          如果取得主窗口的指针成功,就调用父类的run()函数显示它,
          并进入监听事件的循环状态,当主窗口关闭时返回。
        */
        if (main_window) {
            run( *main_window );
        }
    }
   
protected:
    /* 通过它访问Glade文件的内容,是一种智能指针,能自动释放占用的资源 */
    Glib::RefPtr<Gnome::Glade::Xml> ref_xml;
   
    Gtk::Window* main_window;         /* 存储主窗口的指针 */
};
 
int main (int argc, char *argv[])
{
    /*
      可以看到,这跟“最简单的Gtkmm程序”非常相似。HelloApp继承自
      “Gtk::Main”类,也需要通过 argc 和 argv 两个参数进行实例化。
    */
    HelloApp app(argc, argv);
   
    /*
      在这个函数中调用Gtk::Main::run函数来实现与上面相同的功能。   
      这里不需要窗口对象作参数,因为它已封装在HelloApp类中了。
    */
    app.show_window();
   
    return 0;
}

$ g++ hellogtkmm.cpp -o hellogtkmm `pkg-config --cxxflags --libs gtkmm-2.0`

$ ./hellogtkmm

将 GTK+ 与 Python 语言绑定,便是 PyGTK。Glade 仍是 PyGTK 的界面快速构建工具,若使用 libglade 格式的界面布局文件,需额外安装相应的库。在 Red Hat 系中执行

$ sudo dnf install pygtk2-devel pygtk2-docs pygtk2-libglade

Debian 系可执行

$ sudo apt-get install python-gtk2-dev python-gtk2-doc python-glade2

Gentoo 中执行

$ sudo sh -c 'echo "dev-python/pygtk doc \
                    dev-python/pygobject doc \
                    dev-python/pycairo doc" >> /etc/portage/package.use'
$ sudo emerge -av pygtk pygtk2-libglade

还需测试一下 PyGTK 开发环境,下面是一个简单 Hello PyGTK 的例子

$ cat hellopygtk.py

from gtk import * 
 
window = GtkWindow(WINDOW_TOPLEVEL) # 创建一个顶层窗口 
window.set_title("Hello, world!") 
window.connect("destroy", mainquit) # 将注销事件与mainquit处理连接 
 
window.show() # 显示主窗口 
mainloop() # 进入事件循环 

$ python hellopygtk.py

附录

作为跨平台的图形用户界面开发工具,GTK+ 程序在非 Unix/Linux 平台上并非原生样式。若有这种需要,wxWidgets 便是一个更好的选择,它是由 C++ 开发的跨平台的图形用户界面开发包。另外,基于 wxWidgets 工具包,还开发了 C/C++ 集成开发环境 Code::Blocks,它是跨平台的集成开发环境。该集成开发环境还为 wxWidgets 图形界面开发提供了快速开发插件 wxSmith。在 Linux 平台上,为了让图形用户界面显示 GTK+ 样式,wxWidgets 封装了 GTK+ 包,因此 wxWidgets 在 Linux 平台上也被命名为 wxGTK。好了,要在 Linux 平台上开发 wxWidgets 程序,安装所有的工具包了。在 Red Hat 系中执行

$ sudo dnf install wxGTK-devel wxGTK-docs codeblocks codeblocks-contrib

Debian 系可执行

$ sudo apt-get install libwxgtk3.0-dev wx3.0-doc wx3.0-headers wx3.0-i18n wx3.0-examples codeblocks codeblocks-contrib

Gentoo 中执行

$ sudo sh -c 'echo "dev-util/codeblocks doc contrib " >> /etc/portage/package.use'
$ sudo emerge -av wxGTK codeblocks

在 Gentoo 上使用 wxWidgets,还需要用 eselect 的选择合适的版本

$ sudo eselect list wxWidgets
$ sudo eselect wxWidgets set 1

在 Linux 使用 wxWidgets 的方法非常简单,它提供了 wx-config 工具帮助 GCC 查找头文件与库文件。例如

$ wx-config --cppflags
$ wx-config --libs

再来看一个编译 wxWidgets 程序的实例

$ g++ hellowx.cpp -o hellowx `wx-config --cppflags --libs`
$ ./hellowx

与 GTK+ 类似,wxWidgets 也有其他语言的绑定,这里介绍一下 wxWidgets 与 Python 的绑定,也即 wxPython 开发包,对应的界面快速设计工具是 wxGlade。它们的安装非常简单,Red Hat 系中执行

$ sudo dnf install wxpython wxpython-devel wxpython-docs wxGlade

Debian 系可执行

$ sudo apt-get install python-wxgtk3.0 python-wxtools python-wxversion python-wxglade

Gentoo 中执行

$ sudo emerge -av wxPython wxglade

测试一下 wxPython 开发环境,下面是一个简单 Hello wxPython 的例子

$ cat hellowxpy.py

import sys, os
from wxPython.wx import *
 
class main_window(wxFrame):
      def __init__(self, parent, id, title):
      	  wxFrame.__init__(self, parent, -1, title, size = (200, 100),style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
      	  self.control = wxTextCtrl(self, -1, style=wxTE_MULTILINE)
      	  self.Show(true)
 
class App(wxApp):
      def OnInit(self):
      	  frame = main_window(None, -1, "wxPython: (A Demonstration)")
      	  self.SetTopWindow(frame)
      	  return true
 
app = App()
app.MainLoop()

$ python hellowxpy.py