文章目录
GTK 简介
GTK(GIMP Toolkit)是一套用于创建图形用户界面(GUI)的开发工具包。它最初是为GNU Image Manipulation Program(GIMP)项目而开发的,但后来发展成为一个独立的开源项目,被广泛用于许多不同的应用程序。
以下是GTK的一些关键特点和信息:
-
跨平台性: GTK是跨平台的,可以在多个操作系统上运行,包括Linux、Windows和macOS。这使得开发人员能够创建一次界面设计,然后在不同平台上部署。
-
编程语言支持: GTK最初是用C编写的,但它支持多种编程语言,包括C、C++、Python、Vala等。这使得开发者可以选择最适合他们的语言来构建应用程序。
-
插件式架构: GTK的设计是模块化的,允许开发者使用或替换特定的组件,以满足他们应用程序的需求。这使得GTK非常灵活,适用于各种不同类型的应用。
-
Widgts和控件: GTK包括丰富的窗口小部件(Widgets)和控件,如按钮、文本框、列表框等,使开发者能够轻松地构建各种用户界面。
-
主题和外观: GTK提供了主题支持,允许开发者定制应用程序的外观和感觉,以适应不同的设计风格和用户喜好。
-
GLib和Pango: GTK使用GLib作为其底层的通用工具库,提供一些数据结构和函数。Pango用于文本渲染,支持复杂的文本布局和国际化。
GTK Github
GTK 官网
- https://www.gtk.org/
- https://www.gtk.org/docs/
- https://docs.gtk.org/gtk4/
GTK 组件文档
- https://docs.gtk.org/gtk4/index.html#classes
- https://docs.gtk.org/gtk4/class.Button.html
GTK 官方示例
github最新版本是 gtk4
git clone https://github.com/GNOME/gtk.git
# 创建 dist
mkdir dist
# 测试代码目录
cd tests
gcc $(pkg-config --cflags gtk4) -o ../dist/testdropdown testdropdown.c $(pkg-config --libs gtk4)
# 运行程序
../dist/testdropdown
GTK 开发环境
注: 以下操作均在 Mac 环境
xcode-select --install
brew install pkg-config
# pkgconfig 路径
find / -name pkgconfig
# 是否支持GTK+
brew search gtk
brew install gtk+3
# 验证 gtk+3
pkg-config --cflags --libs gtk+-3.0
配置环境变量
# 检查 pkgconfig 路径
find / -name pkgconfig
# 将以上路径添加到环境变量中(.bash_profile 或 .zshrc)
vim ~/.zshrc
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/:$PKG_CONFIG_PATH
source ~/.zshrc
安装 Glade
Glade是一个用于创建GTK图形用户界面的用户界面构建器。它允许开发者通过可视化方式设计和布局GUI元素,而不必手动编写代码。Glade生成XML格式的描述文件,描述了用户界面的结构和属性。然后,这个XML文件可以由程序加载和解释,从而创建用户界面。
- 可视化设计:Glade提供了一个直观的图形用户界面,允许用户通过拖放方式设计和布局界面元素,无需手动编写代码。
- 生成XML描述文件:设计完成后,Glade会生成一个XML格式的描述文件,其中包含了用户界面的结构和属性信息。
- 与多种编程语言兼容:由于生成的描述文件是基于XML的,因此可以与多种编程语言一起使用。GTK支持多种编程语言,包括C、C++、Python等。
- 与IDE集成:Glade可以与多个集成开发环境(IDE)一起使用,例如GNOME Builder,以便更方便地进行开发和调试。
- Glade Github
- https://github.com/GNOME/glade
- https://gitlab.gnome.org/GNOME/glade
- Glade 教程
- https://developer.gnome.org/
- 安装 Glade
# 目前版本支持gtk+3
brew install glade
glade --version
# 启动glade
glade
-
Glade 操作界面
-
保存后会生成如下 demo.glade 文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="window">
<property name="width-request">400</property>
<property name="height-request">200</property>
<property name="can-focus">False</property>
<property name="title" translatable="yes">demo</property>
<child>
<object class="GtkBox" id="box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton" id="button">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="combobox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="active">0</property>
<property name="active-id">1</property>
<items>
<item id="1" translatable="yes">item1</item>
<item id="2" translatable="yes">item2</item>
<item id="3" translatable="yes">item3</item>
<item id="4" translatable="yes">item4</item>
</items>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
完整示例 demo.c
示例使用 gtk+3 与 demo.glade 文件构建界面
#include <gtk/gtk.h>
static void
on_button_clicked (GtkButton *button, gpointer user_data)
{
g_print ("Hello World\n");
}
static void
on_combobox_changed (GtkComboBox *combobox, gpointer user_data)
{
gint active_item = gtk_combo_box_get_active (combobox);
const gchar *active_id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combobox));
g_print ("Selected item: %d, active_id: %s\n", active_item, active_id);
}
static void
on_entry_changed (GtkEntry *entry, gpointer user_data)
{
const gchar *text = gtk_entry_get_text (entry);
g_print ("Entry Text: %s\n", text);
}
static void
on_entry_activate (GtkEntry *entry, gpointer user_data)
{
const gchar *text = gtk_entry_get_text (entry);
g_print ("Entry Text: %s\n", text);
}
int
main (int argc, char **argv)
{
GtkBuilder *builder = gtk_builder_new ();
GtkWidget *window;
GtkWidget *button;
GtkWidget *combobox;
GtkWidget *entry;
gtk_init (&argc, &argv);
gtk_builder_add_from_file (builder, "demo.glade", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
button = GTK_WIDGET (gtk_builder_get_object (builder, "button"));
combobox = GTK_WIDGET (gtk_builder_get_object (builder, "combobox"));
entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect (button, "clicked", G_CALLBACK (on_button_clicked), NULL);
g_signal_connect (combobox, "changed", G_CALLBACK (on_combobox_changed), NULL);
g_signal_connect (entry, "changed", G_CALLBACK (on_entry_changed), NULL);
g_signal_connect (entry, "activate", G_CALLBACK (on_entry_activate), NULL);
g_object_unref (G_OBJECT (builder));
gtk_widget_show (window);
gtk_main ();
return 0;
}
运行效果
# 编译demo.c
gcc $(pkg-config --cflags gtk+-3.0) -o demo demo.c $(pkg-config --libs gtk+-3.0)
# 或
gcc -o demo demo.c `pkg-config --cflags --libs gtk+-3.0`
# 执行编译后文件demo
./demo
GTK 主题
- https://www.gnome-look.org/browse?cat=135&ord=latest
推荐主题
-
https://www.gnome-look.org/p/1403328
-
https://github.com/vinceliuice/WhiteSur-gtk-theme
-
https://www.gnome-look.org/p/1357889
-
https://github.com/vinceliuice/Orchis-theme
-
https://github.com/vinceliuice/Mojave-gtk-theme
-
https://github.com/paullinuxthemer/Prof-Gnome
全局主题配置
- GTK主题
# Mac 主题文件解压到.themes
# Windows msys64/mingw64/share/themes
cd ~/.themes
# 确保文件夹包含诸如 index.theme 文件以及其他图标和资源文件
ls ~/.themes/WhiteSur-Dark
- 设置主题
# Mac GTK配置文件settings.ini
# Windows msys64/mingw64/etc/gtk-3.0
vim ~/.config/gtk-3.0/settings.ini
# 添加主题
[Settings]
gtk-theme-name = WhiteSur-Dark
gtk-icon-theme-name = WhiteSur-Dark
-
运行效果
-
更新GTK缓存
gtk-update-icon-cache -f ~/.themes/WhiteSur-Dark
项目主题配置
- 项目目录结构
├── bin
│ ├── demo
│ ├── demo.c
│ ├── demo.glade
├── etc
│ ├── gtk-3.0
│ ├── settings.ini
├── share
│ ├── themes
│ ├── Orchis-Dark
│ ├── WhiteSur-Dark
└──
- 配置文件指定主题
# 存放主题文件目录
mkdir ./share/themes
# GTK主题配置文件
vim ./etc/gtk-3.0/settings.ini
# 在settings.ini中配置项目主题
[Settings]
gtk-theme-name = WhiteSur-Dark
gtk-icon-theme-name = WhiteSur-Dark
- 通过代码指定主题
代码优先级高于settings.ini配置文件
int
main (int argc, char **argv)
{
gtk_init (&argc, &argv);
// 配置主题
g_object_set (gtk_settings_get_default (), "gtk-theme-name", "WhiteSur-Dark", NULL);
g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", "WhiteSur-Dark", NULL);
}
- GTK_CSD配置(默认值为0)
GTK_CSD=1时应用样式完全按主题样式
int
main (int argc, char **argv)
{
gtk_init (&argc, &argv);
// 设置环境变量,GTK_CSD=1应用主题样式
putenv ("GTK_CSD=1");
}
Mac 电脑上显示效果
vscode开发环境
- .vscode/c_cpp_properties.json
GTK+3的includePath目录可以通过Python脚本生成
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**",
"/usr/local/include"
],
"defines": [],
"macFrameworkPath": [
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks"
],
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-x64",
"compilerPath": "/usr/bin/gcc"
}
],
"version": 4
}
Python脚本列出GTK+3的includePath头文目录
import subprocess
import json
def get_gtk_info():
try:
# 运行命令并捕获输出
output = subprocess.check_output(
['pkg-config', '--cflags', '--libs', 'gtk+-3.0']).decode().strip()
# 解析输出并提取包含路径
include_paths = []
for part in output.split():
if part.startswith("-I"):
include_paths.append(part[2:])
# 构建JSON数据
data = {"includePath": include_paths}
return data
except Exception as e:
print(f"Error getting GTK information: {e}")
return None
def main():
gtk_info = get_gtk_info()
if gtk_info:
# 输出JSON数据
print(json.dumps(gtk_info, indent=4))
if __name__ == "__main__":
main()