有些动作action有状态。状态的典型值是布尔值或字符串。但是,如果你愿意,也可以使用其他类型的状态。
具有状态的动作称为有状态的。
Stateful action without a paramete
有些菜单被称为切换菜单。例如,全屏菜单有一个状态,它有两个值——全屏和非全屏。每次单击菜单时,状态的值都会改变。一个动作对应全屏菜单也有一个状态。它的值为TRUE或FALSE,称为布尔值。TRUE表示全屏,FALSE表示非全屏。
下面是除信号处理程序之外实现全屏菜单的示例代码。稍后将介绍信号处理程序。
GSimpleAction *act_fullscreen = g_simple_action_new_stateful ("fullscreen",
NULL, g_variant_new_boolean (FALSE));
g_signal_connect (act_fullscreen, "change-state", G_CALLBACK (fullscreen_changed), win);
g_action_map_add_action (G_ACTION_MAP (win), G_ACTION (act_fullscreen));
... ... ...
GMenuItem *menu_item_fullscreen = g_menu_item_new ("Full Screen", "win.fullscreen");
- act_fullscreen是一个GSimpleAction实例。它是用g_simple_action_new_stateful创建的。这个函数有三个参数。第一个参数"fullscreen"是操作的名称。第二个参数是形参类型。NULL表示操作没有参数。第三个参数是动作的初始状态。它是一个GVariant值。下一小节将解释GVariant。函数g_variant_new_boolean (FALSE)返回一个GVariant值,即布尔值FALSE。如果有两个或更多的顶层窗口,每个窗口都有自己的act_fullscreen操作。因此,操作的数量与窗口的数量相同。
- 连接动作act_fullscreen和“change-state”信号处理程序fullscreen_changed。如果单击全屏菜单,则激活相应的动作act_fullscreen。但没有处理器连接到"激活"信号。然后,对于具有NULL参数类型(如act_fullscreen)的布尔声明的操作,默认行为是通过“change-state”信号切换它们。
- 该操作被添加到GtkWindow win中。因此,行动的范围是 “win” – window。
- menu_item_fullscreen是一个GMenuItem实例。有两个参数。第一个参数"Full Screen"是menu_item_fullscreen的标签。第二个参数是一个动作。动作“赢”。Fullscreen “前缀是"win”,操作名称是" Fullscreen "。前缀表示操作属于窗口。
1 static void
2 fullscreen_changed(GSimpleAction *action, GVariant *value, GtkWindow *win) {
3 if (g_variant_get_boolean (value))
4 gtk_window_maximize (win);
5 else
6 gtk_window_unmaximize (win);
7 g_simple_action_set_state (action, value);
8 }
- fullscreen_changed处理程序有三个参数。第一个参数是发出“change-state”信号的动作。第二个参数是操作的新状态的值。第三个参数是一个用户数据,在g_signal_connect中设置。
- 如果值是布尔类型且为TRUE,则最大化窗口;否则unmaximizes。
- 用value设置操作的状态。注意:第二个参数是切换后的状态值,但在此阶段,操作的状态具有原始值。因此,您需要通过g_simple_action_set_state用新值设置状态。
你可以使用“activate”信号代替“change-state”信号,或者同时使用两种信号。但上面的方法是最简单也是最好的。
GVariant
GVarient可以包含布尔值、字符串或其他类型的值。例如,下面的程序将TRUE赋值给类型为GVariant的值。
GVariant *value = g_variant_new_boolean (TRUE);
另一个例子是:
GVariant *value2 = g_variant_new_string ("Hello");
value2是一个GVariant,它的值是字符串类型"Hello"。GVariant可以包含其他类型,如int16、int32、int64、double等。
如果你想获得原始值,可以使用g_variant_get系列函数。例如,可以使用g_variant_get_boolean获取布尔值。
gboolean bool = g_variant_get_boolean (value);
因为value被创建为布尔类型GVariant和TRUE value,所以bool等于TRUE。同样,你可以从value2中得到一个字符串
const char *str = g_variant_get_string (value2, NULL);
第二个形参是一个指向gsize类型变量的指针(gsize定义为unsigned long)。如果它不是NULL,那么字符串的长度将由函数设置。如果是NULL,什么都不会发生。返回的字符串str不能更改。
Stateful action with a parameter
另一个有状态操作的例子是与颜色选择菜单相对应的操作。例如,有三个菜单,每个菜单分别有红色、绿色和蓝色。它们确定GtkLabel部件的背景颜色。一个操作连接到三个菜单。这个动作有一个值为"red"、"green"或"blue"的状态。值是字符串。这些颜色作为参数提供给信号处理程序。
... ... ...
GSimpleAction *act_color = g_simple_action_new_stateful ("color",
g_variant_type_new("s"), g_variant_new_string ("red"));
GMenuItem *menu_item_red = g_menu_item_new ("Red", "app.color::red");
GMenuItem *menu_item_green = g_menu_item_new ("Green", "app.color::green"

文章介绍了如何使用GSimpleAction创建具有状态的动作,如全屏切换和颜色选择。全屏菜单通过GSimpleAction的状态切换窗口的最大化和非最大化,颜色选择菜单则通过GVariant传递字符串参数来改变标签的背景颜色。GVariant可以存储不同类型的值,包括布尔值和字符串。信号处理程序如“change-state”和“activate”用于响应用户操作。文章还提供了示例代码来展示这些概念的实际应用。
最低0.47元/天 解锁文章
442

被折叠的 条评论
为什么被折叠?



