croyoux's blog

用 gtk4 写 todo

终于考完了,期末考9科实在是太折磨了;发现自己很久没写文章了,上次更新还在去年,最近都在探索gtk, 就顺便写一篇记录下成果。

工具

gtk主要参考的就是官方的API reference,目前支持gtk3-4(我想也没人会去用gtk3以前的版本)的内容;其中包含 一个Widget Gallery,里面有所有当前版本的控件介绍和API。

官方的文档我认为还是很详细的,但有时候不清楚怎么使用时也还是需要去搜索用例,官方的文档一般不包含示例

IDE

和gtk有关的ide我目前找到的是Gnome Builder,介绍说是Gnome环境下的开发工具;我曾经用它编写过一些小 项目,但我认为它的补全和插件都不够完善,所以转而使用Vscode。

真要说起来,gtk的编写应该只需要一个文本编辑器,gtk4的大部分函数名都比较好记,这方面IDE也只是方便补全一些变量和函数名,提供高亮支持

构建工具

和上文说的一样,你可以选择不使用任何构建工具,使用pkg-config查找依赖和cflags后手动编译;但这样太过原始了,也不方便调试

Meson

Meson是gnome项目主要的编译工具,Gnome Builder也会默认安装此工具,它基于一个简单的构建配置生成build.ninja,有点像Cmake和Makefile。

此外,在build目录下会生成compile_commands.json,clangd可以根据此文件提供高亮和补全支持;Meson还支持增量编译,比直接重新编译更快。

Meson的文档中就包含构建gtk的示例,用dependency提供名称,Meson就能自动查找并引入依赖

1deps = [dependency('gtk4'), dependency('libadwaita-1'), dependency('libcjson')]

libadwaita-1

在依赖中引入Adw能让gtk应用更加现代化,符合Gnome的风格;使用方式和默认的gtk初始化相似

1g_autoptr (AdwApplication) app = NULL;
2app = adw_application_new ("org.example.Hello", G_APPLICATION_DEFAULT_FLAGS);

创建app并用adw_application_new()初始化;官方示例中的G_APPLICATION_FLAGS_NONE已被弃用,用G_APPLICATION_DEFAULT_FLAGS代替

UI绘制

我选择在ui.c中绘制ui,将apphome_ui绑定

1g_signal_connect (app, "activate", G_CALLBACK (home_ui), NULL);

搜索

gtk提供了名为SearchEntry的控件用于搜索,还有一个信号GtkSearchEntry::search-changed,据文档说,

To make filtering appear more reactive, it is a good idea to not react to every change in the entry text immediately, but only after a short delay

也就是延迟操作输入的内容

输入处理

在获取到查询内容后,先删除原有的todo,再循环匹配所有目标类型的符合todo

1if (!strcmp (Todo_s.type[i], Todo_type)) // 目标类型
2{
3    if (strstr (Todo_s.event[i], target) != NULL) // 包含输入的todo
4    {
5    }
6}

再分别处理doneundone类型的todo

1if (!strcmp (Todo_type, "done"))
2{
3    gtk_check_button_set_active (GTK_CHECK_BUTTON (ckbox_todo), true); // 设置状态为true(已完成)
4    gtk_widget_set_sensitive (ckbox_todo, FALSE); // 将checkbox设为非敏感
5}
6else
7{
8    g_signal_connect (ckbox_todo, "toggled", G_CALLBACK (change_todo_to_done), NULL);
9}

样式

gtk支持用类css格式设置控件的样式,如字体大小,背景等

我也不知道怎么翻译provider更好,就当作css样式的提供者

1GtkCssProvider *provider;
2
3provider = gtk_css_provider_new ();

加载样式

1gtk_css_provider_load_from_string (provider, "checkbutton {"
2                                                 " font-size: 22px;"
3                                                 " background-color: #322f3b;"
4                                                 " border-radius: 10px;"
5                                                 "}");
6gtk_style_context_add_provider_for_display (gdk_display_get_default (), GTK_STYLE_PROVIDER (provider),
7                                                GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

也可以直接用gtk_widget_set_size_request()函数调整大小

添加todo

点击添加时在中间创建EnteyButton,点击取消确定时删除

1gtk_center_box_set_center_widget (GTK_CENTER_BOX (Cntbox), NULL);

删除控件

容器中包含删除函数,可以用gtk_widget_get_first_child (<Containers)获取控件后用gtk_box_remove (GTK_<CONTAINER> (<Container>), widget)删除

成品

完成后的效果如下

todo_gtk 有点粗糙,有一些想实现的功能搁置了,后续慢慢更新吧

Gitlab: todo_gtk

Tags: