560 字
3 分钟
GTK 学习笔记——事件和信号
前言
在 GTK 应用中,事件(Event)是通过信号(Signal)来触发的,类似 JS 前端开发中所使用的 EventListener。在点击控件后,不同的控件会发送不同的信号,例如 BoxListRow
会发送 row-activated
信号,当程序捕捉到此信号后,便可根据信号携带的参数进行对应的操作。
使用方法
此处以 GtkBoxList
为例。我们新建一个 Gnome 项目,其结构如下:
├── COPYING
├── data
│ ├── icons
│ │ ├── hicolor
│ │ │ ├── scalable
│ │ │ │ └── apps
│ │ │ │ └── com.example.svg
│ │ │ └── symbolic
│ │ │ └── apps
│ │ │ └── com.example-symbolic.svg
│ │ └── meson.build
│ ├── meson.build
│ ├── com.example.desktop.in
│ ├── com.example.gschema.xml
│ ├── com.example.metainfo.xml.in
│ └── com.example.service.in
├── meson.build
├── po
│ ├── LINGUAS
│ ├── meson.build
│ └── POTFILES.in
├── README.md
├── src
│ ├── gtk
│ │ └── help-overlay.ui
│ ├── main.c
│ ├── meson.build
│ ├── example-application.c
│ ├── example-application.h
│ ├── example.gresource.xml
│ ├── example-window.c
│ ├── example-window.h
│ └── example-window.ui
└── com.example.json
在 example-window.ui
中,我们新增一个 GtkBoxList
控件,并添加若干个 GtkBoxListRow
子控件,同时赋予其 id
和 name
属性。
<object class="GtkListBox" id="box_list">
<property name="selection-mode">none</property>
<child>
<object class="GtkListBoxRow" id="home_btn">
<property name="child">
<object class="GtkLabel">
<property name="label">Home</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="settings_btn">
<property name="child">
<object class="GtkLabel">
<property name="label">Settings</property>
</object>
</property>
</object>
</child>
</object>
在 example-window.c
中,我们需要在 _ExampleWindow
结构体中添加 GtkBoxList
的指针:
struct _ExampleWindow
{
AdwApplicationWindow parent_instance;
GtkListBox *box_list;
}
然后在 example_window_class_init
中将其绑定到窗口中:
static void
example_window_class_init(ExampleWindowClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_template_from_resource (widget_class, "/com/example/example-window.ui");
gtk_widget_class_bind_template_child (widget_class, V2raygWindow, box_list);
}
然后我们在写一个事件处理函数,用于实现不同的功能:
static void
on_row_activated (GtkListBox *box, GtkListBoxRow *row, gpointer user_data)
{
ExampleWindow *self = EXAMPLE_WINDOW (user_data); // EXAMPLE_WINDOW () 是用于强制转换类型的方法,可以将 user_data 转换成 ExampleWindow 类型的变量
int index = gtk_list_box_row_get_index (row); // 获取被点击的 GtkListBoxRow 的行索引,其实就是此控件在 GtkListBox 数组中的位置
switch (index)
{
case "0": ...; break;
case "1": ...; break;
default:
return;
}
... // 其他处理流程
}
最后,我们需要将信号连接到 on_row_activated
函数中:
static void
example_window_init (ExampleWindow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
g_signal_connect (self->box_list, "row-activated", G_CALLBACK (on_row_activated), self);
}
这样我们就可以通过点击 GtkListBoxRow
来实现点击事件了。
简单总结一下:
- 将控件绑定到窗口类中
- 编写事件处理函数
- 将事件处理函数和信号连接在一起
GTK 学习笔记——事件和信号
https://blog.see2night.top/posts/gtk-学习笔记事件和信号/