感觉会一点 GUI 开发挺有用,试试了解下 GTK 开发,起码能写个最简单的计算器。
macOS 上用 brew install gtk+3
安装 GTK 3,小心 gtk+
formula 是 GTK 2。
00-version.c 打印 GTK+ 版本号
用 gtk_major_version
宏能访问到编译所用的 GTK 版本.
01-hello.c 显示窗口 GtkWindow
显示一个空白的窗口,没别的。
02-label.c 标签 GtkLabel
显示一个标签。
03-button.c 按钮 GtkButton
显示一个按钮,用户点击时打印一条消息。
04-image.c 图片 GtkImage
显示一张图片。
05-input.c 用户输入 GtkEntry
接收用户输入,用户按确定键,打印输入。
06-layout.c 布局 GtkBox
单列布局,两个标签一个按钮竖着拍出一列,按钮高度不扩大。
07-file-choose-dialog.c 文件选择器 GtkFileChooserNative
分别尝试 GTK 和 macOS 系统风格,前者有点儿小清新,当然首选系统风格的。
08-progress-bar.c 进度条 GtkProgressBar
使用定时器更新进度条。
09-separator.c 间隔线 GtkSeparator
在两个标签之间画一条间隔线。
10-tooltip.c 提示符 GtkTooltip
3 种 tooltip
- 纯文本
- Pango Markup
- 自定义
11-multiline-text.c 跨行文本框 GtkTextView
显示一个跨行文本框,用户可以编辑。
12-http-request-sync.c 同步地 HTTP 请求
依赖 libsoup 「HTTP client/server library for GNOME」,需要单独安装: brew install libsoup
。
等待用户输入一个 URL,使用 soup_session_send_message
同步地发 HTTP 请求,显示结果。
13-parse-json.c 读取 JSON (json-glib)
试了两种方法 JsonPath 和 JsonReader ,中文(UTF-8)有问题,不知道为什么。另外没想到 C 读取个 JSON 这么不容易。
14-events.c 处理窗口缩放、拖拽移动事件
- 要处理窗口移动和缩放,响应 configure-event
- 要处理窗口拖拽,响应 button-press-event,用 gtk_window_begin_move_drag 移动窗口
15-dialog.c 对话框
各种对话框:
- 自定义
- 消息
- 关于
- 颜色选择
- 字体选择
16-clipboard.c 读写剪切板
- gtk_clipboard_wait_for_text 读取
- gtk_clipboard_set_text 写入
17-process.c 子进程
同步和异步子进程,异步子进程的 IO 不会用。
18-gio-readfile.c GIO 读取文件
- g_file_new_for_path 创建 GFile
- g_file_read 创建 GFileInputStream
- g_input_stream_read 读取 stream
19-frame.c 装饰性边框 GtkFrame
阴影基本看不出效果来,起码 macOS 是如此,是不是 GTK 主题跟 macOS 不协调?
20-status-bar.c 状态栏 GtkStatusbar
用 gtk_statusbar_push 更新状态栏信息。
21-gtk-grid.c 网格布局 GtkGrid
使用 gtk_grid_attach 添加元素。
22-list-view.c 列表控件 GtkTreeWidget
GtkTreeWidget 采用 Model/View/Control
- GtkListStore 是 Model,往里面添加数据,用到 GtkTreeIter gtk_list_store_append gtk_list_store_set
- GtkWidget 是 View,添加栏用 GtkTreeViewColumn,单元格显示用 GtkCellRenderer 控制
- 用 GtkTreeSelection 响应用户选择
23-search-entry.c 搜索控件 GtkSearchEntry
修改之后 150 毫秒 GtkSearchEntry 会发出 search-changed 信号。
24-tree-view.c 带层级的列表控件 GtkTreeView
用 gtk_tree_store_set 插入列,不同 GtkTreeIter 表示层级。
25-cairo.c 画图 GtkDrawingArea
GtkDrawingArea 是画图控件,响应它发出的 draw 信号,然后用它传递过来的 cairo_t 作图。
26-gtk-grid-2.c 网格布局 GtkGrid
用 gtk_grid_attach 添加元素,参数
- `GtkGrid * grid`
- `GtkWidget * child` 要加的元素
- `gint left` X 坐标, 从零开始计数
- `gint top` Y 坐标,从零开始计数
- `gint width` 占几列
- `gint height` 占几行
复制 https://python-gtk-3-tutorial.readthedocs.io/en/latest/layout.html#grid 的效果。
27-list-box.c 列表容器 GtkListBox
GtkListBox 是个垂直的列表控件,元素可以选中、排序、过滤,相比之下 GtkTreeWidget 更加一般化。
28-popover.c 弹出菜单 GtkPopover
GtkTooltip 鼠标悬停自动弹出窗口,GtkPopover 需要用户点击,GtkPopover 是个容器,添加什么元素就显示什么,需要调用 gtk_widget_show 和 gtk_popover_popup 显示。
29-stack.c 换页控件 GtkStack
GtkStack 是个容器,把显示的也页面加入其中,再用 GtkStackSwitcher 得到一个换页 Tab bar。
30-headerbar.c 定制标题栏
用 GtkHeaderBar 替换自带标题栏。
31-flowbox.c GtkFlowBox 水平或垂直自适应
比如一行放 100 个按钮,显然放不下,用 GtkFlowBox 之后空间不够时自动换行。
注意如果内容多,窗口怎么也放不下,应该用 GtkScrolledWindow 包裹起来,比如窗口过大。
32-notebook.c 标签页 GtkNotebook
GtkNotebook 是个容器,像书一样,往里面添加页,每次只显示其中一页。更浏览器 Tab 页一个意思。
33-spinner.c 加载动画 GtkSpinner
GtkSpinner 控件分别用 gtk_spinner_start/stop 控制开关。
34-glib-the-easy-parts.c GLib 简单部分
试用 GLib 容易理解和使用的 API。
35-glib-the-data-types.c GLib 数据结构
- GString 动态字符串
- GArray 动态数组,但元素类型(大小)必须一致
- GHashTable 哈希表,键必须可比较(即能判断两个是否相同,所以键类型应该一样?),值无所谓
- GList 动态列表,元素是指针
- GQueue 队列
- GTree 🌲
36-gtk-css.c GtkCssProvider 用 CSS 定制 GTK
用 gtk_widget_set_name 添加 ID,给 CSS 当选择器。
用 GTK_DEBUG=interactive ./36-gtk-css
调出交互 Debugger,可以实时改变 CSS。
37-pango.c Pango 文字排版
用 PangoLayout 存储文字内容,用 PangoFontDescription 设置字体,用 pango_cairo_show_layout 显示。
用 Pango 可以中文竖排,见 https://pango.gnome.org/ScriptGallery 截图,目前还不清楚代码怎么弄。
38-gio-http-req.c HTTP request with GIO
目的是实现 curl example.com
。
用 g_socket_client_connect_to_host 建立连接,然后通过 GOutputStream 和 GInputStream 输入输出。有一个问题是不知道服务器的输出结束了没,我以为该报 EOF 却没报。
39-gtksourceview.c GtkSourceView 编辑器库
安装 brew install gtksourceview4
。
GtkSourceView 是 GtkTextView 的扩展(子类),分别用 GtkSourceView 和 GtkSourceBuffer 控制显示和内容。
40-gspell.c 拼写检查
安装 brew install gspell
。
可以给 GtkEntry 和 GtkTextView 加上拼写检查。
41-terminal.c 终端应用 VTE
安装 brew install vte3
。
VteTerminal 是个 GTK 控件,用 vte_terminal_spawn_async 启动 shell。
42-async-countdown.c Async 编程基础之单个操作
https://developer.gnome.org/programming-guidelines/stable/async-programming.html.en#single-call
倒计时 5 秒,加个取消的按钮。
调用 xxx_async 启动异步,提供一个结束的回调函数 GAsyncReadyCallback,在这个回调函数中调用 xxx_finish 获得返回值(或者错误)。调用 xxx_async 时还可以提供一个 GCancellable 对象,后续调用 g_cancellable_cancel 就能取消该异步操作。
- GNOME Developer Center 主要就是 API Reference
- GTK+ programming tutorial 注意针对 GTK 2 而不是 GTK 3
- Valadoc.org – Stays crunchy. Even in milk. 搜索 API 文档
- The Python GTK+ 3 Tutorial — Python GTK+ 3 Tutorial 3.4 documentation 比较新