sec5-属性

news2024/11/18 21:44:39

1 属性

GObject系统提供属性。属性是由实例保存的值,实例是GObject的后代,它们对其他实例开放。可以通过他们的名字访问他们。

例如,GtkWindow具有"title"、“default-width”、"default-height"等属性。字符串"title"是属性的名称。属性的名称是一个字符串,以字母开头,然后是字母、数字、破折号(‘-’)或下划线(‘_’)。破折号和下划线用作分隔符,但它们不能混合使用。使用dash比使用underscore更高效。例如,“value”、"double"和"double-value"是正确的属性名。“_value”或“-value”不正确。

属性的值有各种类型。"title"属性的类型是string。"default-width"和"default-height"的类型都是int。

属性是通过GObject中定义的函数来设置和获取的。

  • 属性可以通过几个GObject函数来设置。通常使用g_object_new和g_object_set。
  • 属性可以通过几个GObject函数获得。通常使用G_object_get。

上面的函数属于GObject,但它们可以用于GObject的任何子类对象。下面是一个GtkWindow的例子,它是GObject的子类对象。

创建一个实例,用g_object_new设置其属性。

GtkWindow *win;
/* 创建对象的时候就给属性赋值 */
win = g_object_new (GTK_TYPE_WINDOW, "title", "Hello", "default-width", 800, "default-height", 600, NULL);

上面的例子创建了一个GtkWindow的实例并设置了属性。

  • “title"属性被设置为"Hello”;
  • "default-width"属性被设置为800。
  • "default-height"属性被设置为600。

g_object_new的最后一个参数是NULL,表示属性列表的结束。

如果您已经创建了一个GtkWindow实例,并且希望设置其标题,则可以使用g_object_set。

GtkWindow *win;
win = g_object_new (GTK_TYPE_WINDOW, NULL);
g_object_set (win, "title", "Good bye", NULL);

可以使用g_object_get获取属性的值。

GtkWindow *win;
char *title;
int width, height;

win = g_object_new (GTK_TYPE_WINDOW, "title", "Hello", "default-width", 800, "default-height", 600, NULL);
g_object_get (win, "title", &title, "default-width", &width, "default-height", &height, NULL);
g_print ("%s, %d, %d\n", title, width, height);
g_free (title);

本节的其余部分是关于在GObject的后代中实现属性。它分为两部分。

  1. 注册一个属性
  2. 定义set_property和get_property类方法来实现g_object_set和g_object_get。

2 GParamSpec

GParamSpec是一个基本对象。
GParamSpec和GObject没有父子关系。GParamSpec保存变量信息。“ParamSpec”是“Parameter specification”的缩写。

例如,

double_property = g_param_spec_double ("value", "val", "Double value",
                                       -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
                                        G_PARAM_READWRITE);

该函数创建一个GParamSpec实例,更准确地说,是一个GParamSpecDouble实例。GParamSpecDouble是GParamSpec的一个子类。

该实例包含以下信息:

  • 值类型是double。函数g_param_spec_double的后缀是double,表示类型。
  • 名字是"value"。
  • 别称是“val”。
  • 描述是"Double value"。
  • 最小值为-G_MAXDOUBLE。G_MAXDOUBLE是double类型中可以保存的最大值。在GLib(2.68.1)参考手册——G_MAXDOUBLE和G_MINDOUBLE中描述。你可能认为double的最小值是G_MINDOUBLE,但事实并非如此。G_MINDOUBLE是double中可以保存的最小正值。
  • 最大值为G_MAXDOUBLE。
  • 默认值为0.0。
  • G_PARAM_READWRITE是一个标志。G_PARAM_READWRITE表示该参数可读可写。

有关更多信息,请参阅GObject API参考。

注册GObject属性时,使用GParamSpec。这是从src/tdouble6中的tdouble.c中提取的。

#define PROP_DOUBLE 1
static GParamSpec *double_property = NULL;

static void
t_double_class_init (TDoubleClass *class) {
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);

  gobject_class->set_property = t_double_set_property;
  gobject_class->get_property = t_double_get_property;
  double_property = g_param_spec_double ("value", "val", "Double value", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE);
  g_object_class_install_property (gobject_class, PROP_DOUBLE, double_property);
}

double_property是一个静态变量。GParamSpec实例被分配给double_property。

g_object_class_install_property安装一个属性。该函数必须在set_property和get_property方法被覆盖后调用。这些方法将在后面解释。g_object_class_install_property函数参数是TDoubleClass类,PROP_DOUBLE(属性id)和GParamSpec实例。属性id用于标识tdouble.c中的属性。它是一个正整数。

3 重写set_property和get_property类方法

属性值因实例而异。因此,该值被存储到对象的每个实例中。

g_object_set被赋予一个值作为参数并存储该值。但是g_object_set如何知道要存储的实例?g_object_set在创建对象之前被编译。因此,g_object_set根本不知道将值存储在哪里。这部分需要由重写对象的编写者编写。

g_object_set首先检查属性和值,然后根据值创建GValue(泛型值)。它调用类中set_property指向的函数。请看下面的图表。
在这里插入图片描述
GObjectClass类中的set_property在GObject程序中指向g_object_do_set_property,它是通过编译gobject .c生成的。TDoubleClass结构的GObjectClass部分(它与TDoubleClass相同,因为TDoubleClass没有自己的区域)是通过复制GObjectClass的内容来初始化的。因此,TDoubleClass类中的set_property指向GObject程序中的g_object_do_set_property。但是g_object_do_set_property并不将值存储到TDouble实例。TDouble对象的编写器使t_double_set_property在TDouble .c中作为函数。并将t_double_set_property的地址赋给TDoubleClass类中的set_property。在图中用红色曲线表示。因此,g_object_set调用t_double_set_property而不是g_object_do_set_property(红色虚线曲线),该值将存储在TDouble实例中。

t_double_set_property和t_double_get_property的程序将在后面显示。

4 GValue

GValue是泛型值。GValue由类型和值组成。

类型是任何Gtype。下表显示了一些GType,但不是全部。

请添加图片描述
如果GValue值的类型为G_TYPE_DOUBLE,则可以使用g_value_get_double函数获取value。

GValue value;
value = ... ... ... (a GValue object is assigned. Its type is double.)
double v;
v = g_value_get_double (&value);

相反,可以使用g_value_set_double设置Gvalue值

g_value_set_double (value, 123.45);

5 t_double_set_property and t_double_get_property

g_object_set从属性变量中的值生成GValue。并调用类中set_property所指向的函数。函数在GObjectClass结构中声明。

struct  _GObjectClass
{
  ... ... ...
  ... ... ...
  /* overridable methods */
  void       (*set_property)		(GObject        *object,
                                         guint           property_id,
                                         const GValue   *value,
                                         GParamSpec     *pspec);
  void       (*get_property)		(GObject        *object,
                                         guint           property_id,
                                         GValue         *value,
                                         GParamSpec     *pspec);
  ... ... ...
  ... ... ...
};

t_double_set_property只是从GValue值中获取值,并将其存储到TDouble实例中。

1 static void
2 t_double_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) {
3   TDouble *self = T_DOUBLE (object);
4 
5   if (property_id == PROP_DOUBLE) {
6     self->value = g_value_get_double (value);
7   } else
8     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
9 }
  • 3:将对象转换为TDouble对象self。
  • 6:设置self->value。分配的值是通过g_value_get_double函数获得的。

用相同的方法,t_double_get_property 存储 self->value 到 GValue。

 1 static void
 2 t_double_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) {
 3   TDouble *self = T_DOUBLE (object);
 4 
 5   if (property_id == PROP_DOUBLE)
 6     g_value_set_double (value, self->value);
 7   else
 8     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 9 
10 }

6 notify信号

当属性被设置时,GObject发出“notify”信号。当你将“notify”信号连接到你的处理程序时,你可以指定一个细节,这是属性的名称。细节用分隔符“::”添加到信号名称中。

g_signal_connect (G_OBJECT (d1), "notify::value", G_CALLBACK (notify_cb), NULL);

如果不指定详细信息,则每当设置任何属性时都会调用处理程序。通常细节是设置好的。

通知信号并不意味着属性的值被改变了。即使设置了相同的值,它也会被触发。您可能希望仅在属性实际更改时才发出通知信号。在这种情况下,使用G_PARAM_EXPLICIT_NOTIFY标记定义GPramSpec。然后,通知信号不会自动发出。相反,您可以调用g_object_notify_by_pspec函数,在属性值实际更改时显式发出“notify”信号。

可以为属性设置setter和getter。但如果只是在setter中设置实例成员,则不会发出notify信号。

void
t_double_set_value (TDouble *d, double value) {
  g_return_if_fail (T_IS_DOUBLE (d));

  d->value = value; /* Just set d->value. No "notify" signal is emitted. */
}

如果用户想要捕捉“notify”信号,他们一定会感到困惑。一个解决方案是在setter中使用g_object_set。此时,即使用户使用了setter函数,也会发出notify信号。

void
t_double_set_value (TDouble *d, double value) {
  g_return_if_fail (T_IS_DOUBLE (d));

  g_object_set (d, "value", value, NULL); /* Use g_object_set. "notify" signal will be emitted. */
}

另一种解决方案是使用g_object_notify_by_pspec显式地发出信号。无论如何,如果你为你的属性创建setter,注意通知信号。

7 定义多个属性

如果定义了多个属性,请使用属性id数组。最好去看Gtk源文件,比如gtklabel.c。GtkLabel有18个属性。

在src/tdouble6目录中有一个例子。

翻译自:GObject tutorial

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

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

相关文章

正经科普:DDos高防ip详解

白衬衫容易发黄, 一般洗衣液很难洗掉, 不少人为此感到头疼, 不妨在洗的时候吃点头痛药。 这边我也不多废话,大家直接看图,高防ip原理如下清洗能力 DDoS高防IP采用BGP链路对接全国各地30家运营商,总防御能力超4T。采用电信云堤近源…

智能优化算法:人工兔优化算法-附代码

智能优化算法:人工兔优化算法 摘要:人工兔优化算法( [Artificial rabbits optimization,RSO)是 Liying Wang等 于 2022 年提出的一种新型元启发式优化算法 。 该算法受来源于自然界中兔子的生存策略的启发,具有寻优能力强&#x…

【2.1】服务拆分--案例Demo

服务拆分--案例Demo服务拆分注意事项:导入服务拆分Demo测试结果:总结知识内容来自于黑马程序员视频教学和百度百科。博主仅作笔记整理便于回顾学习。如有侵权请私信我。 服务拆分注意事项: 比如现在有一个需求,是查询订单&#x…

国产GPU芯片突破重围,迎来新发展,中国崛起的力量

最近,在GPU芯片领域我们终于迎来新进展,有望突破欧美企业垄断,实现完全国产化。高端GPU芯片对科技发展有着重要作用,广泛应用于云上服务、高密度高性能计算等领域,然而绝大部分GPU芯片市场都被英伟达、AMD、微软等国外…

骨传导耳挂式耳机排名前十名,最好的骨传导耳机推荐

挂耳式的骨传导耳机在佩戴时更舒适以及更加牢固,日常在多种场景使用都能完全兼顾。但是最好的骨传导耳机有哪些呢?还不知道如何选择骨传导耳机,可以看看这五款骨传导耳机~ 1、南卡Runner Pro4骨传导蓝牙耳机 ¥1498 选择骨传导耳机…

Kubernetes那点事儿——控制器Deployment

K8s应用程序生命周期管理——控制器Deployment一、部署应用程序流程二、Deployment控制器1、应用升级、弹性伸缩、回滚、删除2、滚动升级、回滚机制3、定义Deployment前言说到K8s程序的生命周期管理我们不得不提到k8s的控制器。其中Deployment是最为常用的controllers&#xff…

Liga妙谈 | 如何快速甄别、高效响应用户反馈?

敏捷开发说要「拥抱变化」,在充满不确定的环境中,唯一不变的正是变化。面对源源不断的市场反馈和需求变更,敏捷团队应该如何平衡「高效迭代」与「响应用户」的关系,既快又好地完成研发任务,交付业务价值? …

FFmpeg 滤镜详解

FFmpeg Filter 1. 概念介绍 在多媒体处理中,术语滤镜(filter)指的是修改未编码的原始音视频数据帧的一种软件工具。 2. 基本原理 ● 在编码前,ffmpeg可以对raw(真实/原)音频和视频使用libavfilter库中的滤镜进行处理。(非压缩…

骨感传导蓝牙耳机怎么样、骨感传导蓝牙耳机有什么特点

在正文开始前,先跟大家说明一下,骨感传导其实就是我们常说的骨传导,两者是相同的意思,只是表达的文字不太一样。我们可以理解为骨感传导耳机骨传导耳机,那既然是这样,骨传导耳机又是利用什么原理传播声音的…

CentOS搭建web服务器,并内网穿透实现公网访问

在web项目中,部署的web站点需要被外部访问,则需要一个媒介,通过把资源放在这个媒介中,再通过所暴露的端口指向这个站点,当外部访问这个媒介所对应的端口时,媒介指向站点,完成访问,像这种类似的媒介,常用的有tomcat容器、Apache等,这边使用Apache来建搭建。 Apache2 是一种流行…

一节摹课丨做会动的电子贺卡,当懂浪漫的成年人

你正在阅读摹客全新内容栏目【一节摹课】。 本栏目会通过一些有趣的、实用的、好看的、新潮的实操案例,分享摹客“设计12”产品矩阵 —— 「1个协作平台2款设计工具」的具体操作妙计! 带大家一步一步地解锁摹客协作、摹客RP、摹客DT中的大小功能。 一…

非正式全面解析 NebulaGraph 中 Session 管理

NebulaGraph 论坛最近有些讨论帖,各种姿势来问 NebulaGraph Session 管理相关的事情,我寻思这也不是一个法子,还是来写一篇文章来讲述下 NebulaGraph 中的 Session 管理。由于本文设定为非正式的 Session 讲解,所以本文主要分为理…

智能车|直流电机、编码器与驱动器---编码器

智能车|直流电机、编码器与驱动器---编码器编码器编码器简介编码器的工作原理四倍频采集编码器采集程序实现编码器 编码器简介 编码器是一种将角位移或者直线位移转换成一连串电数字脉冲的一种传感器。 可以通过编码器测量电机转动的位移或者速度信息。 编码器按照工作原理…

FTP多目录和多用户配置(用户隔离/虚拟目录)

FTP多目录和多用户配置(用户隔离/虚拟目录) 假设有四个部门分别是user1、user2、user3、admin。要求四个部门都有各自有独立的访问目录,且admin部门可以访问其他部门的文件但不能对其进行修改。 1、创建ftp文件→再创建LocalUser(…

【图像处理OpenCV(C++版)】——3.1几何变换之仿射变换

前言: 😊😊😊欢迎来到本博客😊😊😊 🌟🌟🌟 本专栏主要结合OpenCV和C来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快…

CSS 颜色

文章目录CSS 颜色关键字 & 十六进制 & RGBopacity 透明度RGBA 颜色CSS3 渐变线性渐变径向渐变CSS 颜色 关键字 & 十六进制 & RGB W3C十六色 opacity 透明度 语法 opacity: 数值;说明 在CSS3中,我们可以使用opacity属性来定义元素的透明度。 o…

excel排序求和:如何统计前几名数据合计 下篇

上次咱们说到一个公式SUM(LARGE(B:B,ROW(INDIRECT("1:"&H2)))),其中的ROW(INDIRECT("1:"&H2))这部分如果写成ROW(1:H2)就会报错: 原因也告诉大家了,就是ROW函数的参数只能使用单元格或单元格区域。 因此解决的办…

Java IO流 - 字节流的使用详细介绍

文章目录IO流的基本介绍字节流的使用文件字节输入流创建字节输入流每次读取一个字节每次读取一个数组一次读取全部字节文件字节输出流创建字节输出流写入文件输出流文件拷贝练习IO流的基本介绍 IO流的概述: I 表示intput,是数据从硬盘文件读入到内存的过程&#xf…

频谱分析仪关键性能指标

频谱分析仪关键性能指标 频谱分析仪作为分析仪表,其基本性能要求包含: 1. 频率方面指标: 测量频率范围:反映频谱仪测量信号范围能力; 频率分辨率:反映频谱仪分辨两个频率间隔信号的能力。 2. 幅方面度指标&#x…

银河麒麟(aarch64)安装Qt,报错main.cpp:8:5: error: unknown type name ‘MainWindow‘...

环境: 版本:银河麒麟桌面操作系统V10(SP1) 内核:Linux 5.4.18-35-generic CPU:Phytium,D2000/8 终端输入 uname -m 查看 架构 aarch64 在商店安装Qt, 安装完成后 工具-选项-kits构…