十九、Gtk4-Ui file for menu and action entries

news2024/10/5 8:35:40

Ui file for menu

你可能认为构建菜单真的很麻烦。是的,程序很复杂,需要很多时间来编码。这种情况类似于构建小构建。当我们构建部件时,使用ui文件是避免这种复杂性的好方法。菜单也是如此。

菜单的ui文件有界面和菜单标签。文件以interface标签开始和结束。

<interface>
  <menu id="menubar">
  </menu>
</interface>

menu标签对应于GMenu对象。Id属性定义对象的名称。它将由GtkBuilder引用。

<submenu>
  <attribute name="label">File</attribute>
    <item>
      <attribute name="label">New</attribute>
      <attribute name="action">win.new</attribute>
    </item>
</submenu>

item标签对应GMenu中的一个item,该项目与GMenuItem具有相同的结构。上面的项有一个label属性。它的值是"New"。这个item还有一个action属性,它的值是"win.new"。"win"是前缀,"new"是动作名称。submenu标签同时对应GMenuItem和GMenu。GMenuItem有一个指向GMenu的链接。

上面的ui文件可以描述如下。

<item>
  <attribute name="label">File</attribute>
    <link name="submenu">
      <item>
        <attribute name="label">New</attribute>
        <attribute name="action">win.new</attribute>
      </item>
    </link>
</item>

link标签表示与submenu的链接。同时也表达了子菜单submenu本身。这个文件比之前的ui文件更好地说明了菜单和菜单项之间的关系。但是子菜单标签简单易懂。所以,我们通常更喜欢前一种ui风格。

有关更多信息,请参阅GTK 4 API参考——PopoverMenu。

下面是示例程序menu3的屏幕截图。它位于目录src/menu3中。
在这里插入图片描述

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <interface>
 3   <menu id="menubar">
 4     <submenu>
 5       <attribute name="label">File</attribute>
 6       <section>
 7         <item>
 8           <attribute name="label">New</attribute>
 9           <attribute name="action">app.new</attribute>
10         </item>
11         <item>
12           <attribute name="label">Open</attribute>
13           <attribute name="action">app.open</attribute>
14         </item>
15       </section>
16       <section>
17         <item>
18           <attribute name="label">Save</attribute>
19           <attribute name="action">win.save</attribute>
20         </item>
21         <item>
22           <attribute name="label">Save As…</attribute>
23           <attribute name="action">win.saveas</attribute>
24         </item>
25       </section>
26       <section>
27         <item>
28           <attribute name="label">Close</attribute>
29           <attribute name="action">win.close</attribute>
30         </item>
31       </section>
32       <section>
33         <item>
34           <attribute name="label">Quit</attribute>
35           <attribute name="action">app.quit</attribute>
36         </item>
37       </section>
38     </submenu>
39     <submenu>
40       <attribute name="label">Edit</attribute>
41       <section>
42         <item>
43           <attribute name="label">Cut</attribute>
44           <attribute name="action">app.cut</attribute>
45         </item>
46         <item>
47           <attribute name="label">Copy</attribute>
48           <attribute name="action">app.copy</attribute>
49         </item>
50         <item>
51           <attribute name="label">Paste</attribute>
52           <attribute name="action">app.paste</attribute>
53         </item>
54       </section>
55       <section>
56         <item>
57           <attribute name="label">Select All</attribute>
58           <attribute name="action">app.selectall</attribute>
59         </item>
60       </section>
61     </submenu>
62     <submenu>
63       <attribute name="label">View</attribute>
64       <section>
65         <item>
66           <attribute name="label">Full Screen</attribute>
67           <attribute name="action">win.fullscreen</attribute>
68         </item>
69       </section>
70     </submenu>
71   </menu>
72 </interface>

资源编译器glib-compile- resources把xml格式ui文件转换为资源resource。

1 <?xml version="1.0" encoding="UTF-8"?>
2 <gresources>
3   <gresource prefix="/com/github/ToshioCP/menu3">
4     <file>menu3.ui</file>
5   </gresource>
6 </gresources>

GtkBuilder从资源中构建菜单。

GtkBuilder *builder = gtk_builder_new_from_resource ("/com/github/ToshioCP/menu3/menu3.ui");
GMenuModel *menubar = G_MENU_MODEL (gtk_builder_get_object (builder, "menubar"));

gtk_application_set_menubar (GTK_APPLICATION (app), menubar);
g_object_unref (builder);

在将GMenuModel菜单栏插入应用程序之后,构建器实例就会被释放。如果你在插入之前这样做,不好的事情会发生——你的电脑可能会死机。

Action entry

构建动作和信号处理程序的编写也是很麻烦的工作。因此,它应该是自动化的。你可以使用GActionEntry结构和g_action_map_add_action_entries函数轻松实现它们。

GActionEntry包含动作名称、信号处理程序、参数和状态。

typedef struct _GActionEntry GActionEntry;

struct _GActionEntry
{
  /* action name */
  const char *name;
  /* activate handler */
  void (* activate) (GSimpleAction *action, GVariant *parameter, gpointer user_data);
  /* the type of the parameter given as a single GVariant type string */
  const char *parameter_type;
  /* initial state given in GVariant text format */
  const char *state;
  /* change-state handler */
  void (* change_state) (GSimpleAction *action, GVariant *value, gpointer user_data);
  /*< private >*/
  gsize padding[3];
};

例如,上一节中的操作如下:

{ "fullscreen", NULL, NULL, "false", fullscreen_changed }
{ "color", color_activated, "s", "'red'", NULL }
{ "quit", quit_activated, NULL, NULL, NULL },
  • 全屏操作是有状态的,但没有参数。因此,第三个元素(参数类型)是NULL。GVariant文本格式提供“true”和“false”作为布尔值。操作的初始状态为false(第四个元素)。它没有activate处理程序,所以第二个元素是NULL。相反,它有change-state处理程序。fullscreen_changed的第五个元素是处理程序。
  • 颜色动作是有状态的,并且有一个参数。参数类型为string。GVariant格式字符串提供了表示GVariant类型的字符串格式。第三个元素“s”表示GVariant字符串类型。GVariant文本格式定义了字符串用单引号或双引号括起来。字符串red是’red’或"red"。第四个元素是"‘red’“,这是一个C字符串格式,字符串是’red’。你可以写成”“red”"。第二个元素color_activated是activate处理程序。这个动作没有change-state处理程序,因此第5个元素是NULL。
  • 退出操作是无状态的,没有参数。因此,第三和第四个元素为NULL。第二个成员quit_activated是activate处理程序。这个动作没有change-state处理程序,因此第5个元素是NULL。

函数g_action_map_add_action_entries负责创建GSimpleAction实例并将它们添加到GActionMap(一个应用程序或窗口)。

const GActionEntry app_entries[] = {
  { "color", color_activated, "s", "'red'", NULL },
  { "quit", quit_activated, NULL, NULL, NULL }
};
g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries,
                                 G_N_ELEMENTS (app_entries), app);

上面的代码做了:

  • 创建"color"和"quit"操作
  • 连接动作和“activate”信号处理程序(color_activated和quit_activated)。
  • 将操作添加到操作映射应用程序。

另一个动作也是如此。

const GActionEntry win_entries[] = {
  { "fullscreen", NULL, NULL, "false", fullscreen_changed }
};
g_action_map_add_action_entries (G_ACTION_MAP (win), win_entries,
                                 G_N_ELEMENTS (win_entries), win);

上面的代码做了:

  • 构建“全屏”操作。
  • 连接动作和信号处理程序fullscreen_changed
  • 它的初始状态设置为false。
  • 将action添加到action map win。

Example

源文件是menu3.c、menu3.ui、menu3.gresource.xml和meson.build。它们位于目录src/menu3中。下面是menu3.c和meson.build。

  1 #include <gtk/gtk.h>
  2 
  3 static void
  4 new_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
  5 }
  6 
  7 static void
  8 open_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
  9 }
 10 
 11 static void
 12 save_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
 13 }
 14 
 15 static void
 16 saveas_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
 17 }
 18 
 19 static void
 20 close_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
 21   GtkWindow *win = GTK_WINDOW (user_data);
 22 
 23   gtk_window_destroy (win);
 24 }
 25 
 26 static void
 27 cut_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
 28 }
 29 
 30 static void
 31 copy_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
 32 }
 33 
 34 static void
 35 paste_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
 36 }
 37 
 38 static void
 39 selectall_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data) {
 40 }
 41 
 42 static void
 43 fullscreen_changed (GSimpleAction *action, GVariant *state, gpointer user_data) {
 44   GtkWindow *win = GTK_WINDOW (user_data);
 45 
 46   if (g_variant_get_boolean (state))
 47     gtk_window_maximize (win);
 48   else
 49     gtk_window_unmaximize (win);
 50   g_simple_action_set_state (action, state);
 51 }
 52 
 53 static void
 54 quit_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data)
 55 {
 56   GApplication *app = G_APPLICATION (user_data);
 57 
 58   g_application_quit (app);
 59 }
 60 
 61 static void
 62 app_activate (GApplication *app) {
 63   GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
 64 
 65   const GActionEntry win_entries[] = {
 66     { "save", save_activated, NULL, NULL, NULL },
 67     { "saveas", saveas_activated, NULL, NULL, NULL },
 68     { "close", close_activated, NULL, NULL, NULL },
 69     { "fullscreen", NULL, NULL, "false", fullscreen_changed }
 70   };
 71   g_action_map_add_action_entries (G_ACTION_MAP (win), win_entries, G_N_ELEMENTS (win_entries), win);
 72 
 73   gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);
 74 
 75   gtk_window_set_title (GTK_WINDOW (win), "menu3");
 76   gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
 77   gtk_widget_show (win);
 78 }
 79 
 80 static void
 81 app_startup (GApplication *app) {
 82   GtkBuilder *builder = gtk_builder_new_from_resource ("/com/github/ToshioCP/menu3/menu3.ui");
 83   GMenuModel *menubar = G_MENU_MODEL (gtk_builder_get_object (builder, "menubar"));
 84 
 85   gtk_application_set_menubar (GTK_APPLICATION (app), menubar);
 86   g_object_unref (builder);
 87 
 88   const GActionEntry app_entries[] = {
 89     { "new", new_activated, NULL, NULL, NULL },
 90     { "open", open_activated, NULL, NULL, NULL },
 91     { "cut", cut_activated, NULL, NULL, NULL },
 92     { "copy", copy_activated, NULL, NULL, NULL },
 93     { "paste", paste_activated, NULL, NULL, NULL },
 94     { "selectall", selectall_activated, NULL, NULL, NULL },
 95     { "quit", quit_activated, NULL, NULL, NULL }
 96   };
 97   g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries, G_N_ELEMENTS (app_entries), app);
 98 }
 99 
100 #define APPLICATION_ID "com.github.ToshioCP.menu3"
101 
102 int
103 main (int argc, char **argv) {
104   GtkApplication *app;
105   int stat;
106 
107   app = gtk_application_new (APPLICATION_ID, G_APPLICATION_DEFAULT_FLAGS);
108   g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL);
109   g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
110 
111   stat =g_application_run (G_APPLICATION (app), argc, argv);
112   g_object_unref (app);
113   return stat;
114 }
115 

meson.build

 1 project('menu3', 'c')
 2 
 3 gtkdep = dependency('gtk4')
 4 
 5 gnome=import('gnome')
 6 resources = gnome.compile_resources('resources','menu3.gresource.xml')
 7 
 8 sourcefiles=files('menu3.c')
 9 
10 executable('menu3', sourcefiles, resources, dependencies: gtkdep)

动作处理程序需要遵循以下格式。

static void
handler (GSimpleAction *action_name, GVariant *parameter, gpointer user_data) { ... ... ... }

例如,你不能写“GApplication *app”而不是“gpointer user_data”。因为g_action_map_add_action_entries期望处理程序遵循上述格式。

有menu2_ui.c和menu2.ui在菜单目录下。它们是显示菜单ui文件和g_action_map_add_action_entries的其他例子。它包括一个带参数的有状态动作。

<item>
  <attribute name="label">Red</attribute>
  <attribute name="action">app.color</attribute>
  <attribute name="target">red</attribute>
</item>

动作名称和目标像这样分开。动作属性只包括前缀和名称。你不能这样写<attribute name="action">app.color::red</attribute>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/180030.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript 基本认识

JavaScript 简介 JavaScript 是什么&#xff1f; JavaScript 是互联网最流行的脚本语言&#xff0c;这门语言可用于 HTML 和 Web&#xff0c;更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。 JavaScript 是脚本语言&#xff1f; HTML 是超文本标记语言&am…

Groovy实现热部署

Groovy实现热部署一、概述二、准备工作2.1 规则接口IRule三、非Spring环境Groovy文件方式3.1 Groovy文件3.2 读取并生成实例3.3 使用这个实现四、数据库Groovy脚本方式4.1 Groovy脚本4.2 读取并生成实例五、Spring中使用Groovy的方式5.1 Groovy文件5.2 读取并生成实例5.3 使用这…

css sprite雪碧图制作,使用以及相关,图文gif

写在前面&#xff1a; 在网页制作中&#xff0c;雪碧图也是前端攻城狮必须掌握的一项小技能。百度词条对雪碧图的解释是&#xff1a;CSS雪碧 即CSS Sprite&#xff0c;也有人叫它CSS精灵&#xff0c;是一种CSS图像合并技术&#xff0c;该方法是将小图标和背景图像合并到一张图…

计算机组成原理 | 第一章:概论 | 冯诺依曼计算机 | 计算机硬件

文章目录&#x1f4da;冯诺依曼计算机的特点&#x1f4da;计算机硬件组成框图&#x1f4da;计算机硬件的主要技术指标&#x1f407;非时间指标&#x1f407;时间指标&#x1f511;计算技巧归纳&#x1f4da;小结&#x1f511;本章掌握要点&#x1f407;补充思考题&#x1f4da;…

[电商实时数仓] 用户行为数据和业务数据采集以及ODS层

文章目录1.数据仓库环境准备1.1 导入依赖1.2 创建相关包2.数据仓库运行环境2.1 Hbase环境2.2 模拟数据3.数仓开发之ODS层3.1 mysql配置修改3.2 FlinkCDC的程序3.3 结果检测1.数据仓库环境准备 1.1 导入依赖 <properties><java.version>1.8</java.version>&l…

为什么你的Facebook广告策略应该包括SEO

最近在看了很多关于 SEO的文章&#xff0c;今天想跟大家分享一些我个人关于 Facebook广告中的 SEO策略&#xff0c;以及它为什么是必要的。虽然在我看来&#xff0c;所有营销手段都需要结合 SEO才能发挥最大作用&#xff0c;但这并不意味着要完全放弃 SEO。如果你对以下问题感兴…

分享147个ASP源码,总有一款适合您

ASP源码 分享147个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 147个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1us1KTsxeaZlosHsqvrkC5Q?pwd81pl 提取码&#x…

Leetcode:51. N 皇后(C++)

目录 问题描述&#xff1a; 实现代码与解析&#xff1a; 回溯&#xff1a; 原理思路&#xff1a; 问题描述&#xff1a; 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&a…

数字电位器程控可调电阻ic

一、前言 数字电位器又叫可编程电阻器&#xff0c;是一种替代传统机械电位器的新型CMOS数字、模拟混合信号处理集成电路&#xff0c;不需要搭建复杂的电路环境即可简单的通过CPU数字通讯实现电路调节&#xff0c;数字电位器也不能完全替代传统的机械电位器&#xff0c;在很多场…

Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60

一&#xff1a;Sentinel简介 Sentinel就是分布式系统的流量防卫兵 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 1.1 官方文档 官方文档&#…

基于OpenXR,Collabora推开源VI-SLAM AR/VR定位系统

XR最关键的难题之一就是定位&#xff0c;为了定位XR头显在现实世界中的位置和角度&#xff0c;厂商们采用了多种方案&#xff0c;比如机械传感器、惯性传感器、磁传感器、声学传感器等等。这些定位方式有一个共同的问题&#xff0c;那就是传感器不够完善&#xff0c;且会产生噪…

uniapp的父传子,子传父,子组件与父组件数据同步(.sync)的理解

父传子&#xff1a; 父调用 绑定的子组件中state然后 mystate1赋值false 给子组件中的state。并在子组件中显示父中传来的值。 注意要在子组件中设置 props【属性】不然父中的值无法传过去。 <view >开启{{mystate1}}</view> --调用子组件mypop&#xff0c;并传值…

学习记录673@项目管理之进度管理案例

本文主要是进度管理之关键链路法的案例。 案例 Perfect 项目的建设方要求必须按合同规定的期限交付系统&#xff0c;承建方项目经理李某决定严格执行项目进度管理&#xff0c;以保证项目按期完成。他决定使用关键路径法来编制项目进度网络图。在对工作分解结构进行认真分析后&…

05 二叉树前序/中序/后序线索化和找前驱、后继

1. 线索化代码 线索化需要先序/中序/后续遍历的过程&#xff0c;多了访问到节点时指针指向的问题 二叉树形状和运行结果 主函数 #include "func.h"// 二叉树线索化(便于找前驱和后继节点) // 1. 二叉树先序线索化 // 2. 二叉树中序线索化 // 3. 二叉树后序线索化//…

《MySQL》MySQL简单操作

最近开始了新的学习进度 进入MySQL数据库的学习 目录 一、MySQL启动方法 1.使用MySQL启动 2.使用cmd启动 二、数据库的简单操作命令 显示当前服务器上有哪些数据库 创建新的数据库 删除数据库 选中数据库 三、数据表的操作 数据类型 四、表的简单操作 查看数据库中的…

Java多线程-线程的生命周期

Java多线程-线程的生命周期 线程的状态 New 表示线程已创建&#xff0c;没启动的状态此时已经做了一些准备工作&#xff0c;还没有执行run方法中代码 Runnable 调用start方法之后的状态&#xff0c;表示可运行状态(不一定正在运行&#xff0c;因为调用start方法之后不一定立…

分享148个ASP源码,总有一款适合您

ASP源码 分享148个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 148个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1e2PvBmXxZA8C3IelkP8ZtQ?pwdj7lp 提取码&#x…

node.js 安装步骤

1、下载安装包 Node.js 官方网站下载&#xff1a;Node.js 选择操作系统对应的包&#xff1a; 下载完成&#xff0c;安装包如下&#xff1a; 2、安装Node 打开安装&#xff0c;傻瓜式下一步即可&#xff1a; 选择安装位置&#xff0c;我这里装在D盘下&#xff1a; 安装成功&…

图和树基础算法笔记

图的大部分知识在《离散数学》中都已经学习了&#xff0c;所以我主要放一些不知道的知识 常用概念 有很少边或弧&#xff08;如 e < n log n&#xff0c;e指边数&#xff0c;n指顶点数&#xff09;的图称为稀疏图&#xff0c;反之称为稠密图。完全图&#xff1a;每个顶点的…

[引擎开发] 现代图形API - dx12篇

本文将从性能优化的角度去阐述像dx12这样的现代图形API的一些设计理念。 当我们深入优化渲染管线的时候&#xff0c;我们会发现存在的几个瓶颈主要是这样的&#xff1a; ① 线程存在不合理的等待 ② CPU向GPU编码传输数据非常耗时 ③ CPU频繁地切换渲染上下文非常耗时 因此有时…