GTK 是由 GNOME 官方推出的 GNOME 桌面环境应用程序开发包。它基于事件驱动,在执行时,会监听应用程序内发生的事件,例如单击鼠标,改变窗体大小,再向应用程序内的组件告知信息。
GTK 支持 C, JavaScript, Python, Rust 等多种语言(你猜为什么没有 Java)。然而,从网页上给出的示例代码来看,本人相对熟悉的 C 语言实现版本较为复杂,而 Python 相对简单,却并非本文所探讨的范畴(你看,分类写的是 C++,所以不会有 Python)。因此,我们这里选用语法风格更像 C++ 的扩展包,也就是 gtkmm 作为这个系列的开发工具包。
开始之前
这个系列使用的默认开发环境如下:
补充:
如果你习惯使用
Ubuntu或者其他发行版也是可以的!这里不做强制要求!这个系列只是以Manjaro为例!(注意,macOS 不支持)如果你对 C++ 的语法规则不熟悉,请先阅读 C++ 教程 。这个系列至少需要你学会 OOP 中的继承部分。
安装 gtkmm
在 Manjaro 上安装 gtkmm 的过程非常简单,只需要一行命令:
sudo pacman -S gtkmm-4.0
在其他系列的发行版上安装 gtkmm 的命令如下:
sudo apt install libgtkmm-4.0-dev
sudo dnf install gtkmm-4.0-dev
某些发行版上相对应的名称和将要安装的软件包版本可能有所不同。
例如,在 Arch Linux 系的发行版中,该软件包有 gtkmm 和 gtkmm-4.0 两个版本,它们所指向的 gtkmm 版本是不一样的(前者是3.0)!这一点可以通过检查比对依赖项版本得出。
一般来说,发行版提供的包管理器都会自动帮我们安装好依赖项。为了方便大家对比,这里列出几个作为参考:

第一个项目
代码实现
打开任意一个代码编辑器(这里我用的是 CLion,其他编辑器也行),创建一个名为 main.cpp 的源文件,并输入(或复制粘贴)以下内容:
// It's OK if you want some other cool names
// This depends on you!
#include <gtkmm.h>
#include <iostream>
// Custom GTK Window Class.
class CustomGTKWindow : public Gtk::Window {
public:
CustomGTKWindow(); // Constructor
};
CustomGTKWindow::CustomGTKWindow() {
set_title("Hello World"); // set default title
set_default_size(800, 600); // set height and width of the window
}
// As you can see this one is much simpler than WinMain and even Qt.
int main(int argc, char *argv[]) {
auto lang = "C++";
std::cout << "Hello and welcome to " << lang << "!\n";
auto app = Gtk::Application::create("org.gtkmm.examples.hello_world");
return app->make_window_and_run<CustomGTKWindow>(argc, argv);
}
(原教程使用 .cc 作为源文件后缀名。.cc 是一种在 Linux/UNIX 系统上广泛使用的 C++ 源文件格式,对该类系统的优化较好。但这里为了更广泛的兼容性,我们仍然采用传统的 .cpp 后缀名。)
如果你的 IDE 内出现以下报错:

请打开同一目录下的 CMakeLists.txt,将里面的内容修改为下面的代码片段:
cmake_minimum_required(VERSION 4.0) # change if there is a newer version
project(hello_world) # replace it with your name
set(CMAKE_CXX_STANDARD 20) # use your own C++ standard, but make sure no earlier than C++ 17
find_package(PkgConfig)
pkg_check_modules(GTKMM gtkmm-4.0) # Not gtkmm-3.0!
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS})
# set(SOURCE_FILES main.cpp MainWindow.cpp MainWindow.h)
add_executable(hello_world main.cpp) # replace it with your name
target_link_libraries(${CMAKE_PROJECT_NAME} ${GTKMM_LIBRARIES})
然后重启 IDE. 问题应该可以得到解决。
具体可以参考一下这个链接:StackOverflow
结果与解释
接下来,我们来编译并运行程序。得到的结果应该和下面相似:

(请注意,如果你用的是 GNOME 桌面环境,那么样式应该和 Adwaita 类似;不同风格的 KDE 桌面环境可能和示例不同)
这是因为我们目前只是添加了一个窗口标题并设定了宽和高。我们先来看看这段代码的含义:
#include <gtkmm.h>
它表示导入 gtkmm.h 库。这对于使用 gtkmm 构建的应用来说是必需的。但是严格意义上说,直接使用这个头文件并不是一个好主意——它含有 1 M 左右大小的标头!很显然这会拖慢编译速度。
下面来看代码最主要的部分,也就是 CustomGTKWindow 类。
// Custom GTK Window Class.
class CustomGTKWindow : public Gtk::Window {
public:
CustomGTKWindow(); // Constructor
};
CustomGTKWindow::CustomGTKWindow() {
set_title("Hello World"); // set default title
set_default_size(800, 600); // set height and width of the window
}
同样地,这个类也是必需的。它必须继承自命名空间(你可以把它理解为和 std 一个效力的东西)Gtk 中定义的类 Window,并且有一个构造函数(析构函数可以不写)。下面构造函数的实现部分则详细展示了初始化窗体时,对窗体进行初步配置的代码。函数很好理解,我就不过多介绍了。
最后,在 main 函数内:
auto app = Gtk::Application::create("org.gtkmm.examples.hello_world");
return app->make_window_and_run<CustomGTKWindow>(argc, argv);
它们的作用是创建并初始化窗体对象,这个过程会调用类的构造函数。
更详细一点说(内容修改自机翻): 程序首先创建的是一个存储在 Glib::RefPtr 智能指针(这是 C++ 11 引入的新特性,相较于传统指针更具有内存安全性)内的 Gtk::Application 对象。create() 方法会初始化 gtkmm。接下来,程序会创建并显示一个窗口并进入 gtkmm 主处理循环(这一点和 tkinter 类似!),该循环将在窗口关闭时完成。然后,main() 函数将返回适当的成功或错误代码。如果从命令行执行程序,argc 和 argv 参数会作为额外参数传递给应用程序。此外在调用 make_window_and_run() 时,系统会检查这两个参数,但今天我们写的这个简单的应用程序并不会使用它们。
结语
至此,你已经成功完成了第一步——创建一个简单的 gtkmm 应用程序。虽然开发一个完整的应用并不是一件很容易的事,但最起码我们已经迈出了决定性的一步。现在,你可以休息一下了!