870920 Menu

JUCE类库ValueTree类详解

先了解一下Identifier类。该类的对象代表一个字符串标识符(属性名称),用于按名称访问属性值。ValueTree使用本类对象作为属性值所对应的属性名称。相比数据类型标识符(比如int、double等),Identifier更加清晰直观,便于使用(一是不用写字符串的””引号,二是该属性是什么一目了然)。而相比于XML中节点的属性名称,其执行效率更高:XML的一切处理都是基于文本字符串的,而Identifier则相当于一个全新的“类型”。

Identifier属于极轻量级类,默认大小为4个字节。使用时声明其栈对象即可。

注意两点:
1、Identifier对象的名称只能由字母、数字、下划线、“-”和“:”构成,不允许其他字符。

2、每次构造对象时,均需基于给出的字符数组或String对象进行初始化,如果本类对象较多且使用频繁,这种创建方式的执行效率并不高。解决方案:将频繁使用的名称定义为静态对象,避免每次需要时均进行构造。可在程序启动时初始化一些需频繁访问的Identifier标识符,用来替代文本字符串。最好将这些标识符置入一个全局性的名称空间中,在文件作用域内使用,或者将其作为某个类的静态成员。

Identifier类的重要方法:
 基于char*或String对象构造对象。拷构和赋值运算符重载。
 ==和!=比较运算符。
 toString() 返回此标识符的字符串
 getCharPointer() 返回此标识符原始字符串的指针(获取指针)
 isValidIdentifier() 静态函数,检测给出的字符串是否满足构造Identifier对象的必要条件

ValueTree值树数据模型:

ValueTree相当于增加了撤销、重做功能并可产生消息的XmlElement类(ValueTree与XmlElement之间可以互相转换),但内部数据并非基于文本格式,而是:属性名称基于Identifier,属性值基于var。程序中一切可读写并需要进行操作处理的数据均可交由本类来完成。与Xml一致,ValueTree也是基于节点的形式组织和管理数据,每个节点均有一个类型名称(对应XML节点的tag)。同时,每个节点可保存一到n个属性,每个属性均由属性名和属性值构成。可基于给出的属性名称设置并获取所对应的属性值。设置时,有则改变,没有则添加。一个节点可成为另一个节点的子节点,同时也可拥有1到n个子节点。每个子节点的类型都可以是不同的。

ValueTree的属性值为var类型,其属性名称则是Identifier文本标识符,而XmlElement全部基于文本方式。正因为此,ValueTree的执行效率更高。

ValueTree更特殊之处在于其内部使用引用计数和写时复制技术,并不实际存储原始数据,所保存的只是引用类型,因此,该类做到了轻量、高效、可关联。并且,当节点的类型或属性发生改变、添加/移除/排序子节点时,均可产生消息。所产生的消息可由继承了ValueTree::Listener的类所捕获并处理(回调)。这一点与按钮消息的产生与捕获处理完全一致。

ValueTree类还可实现撤销与重做功能,该类所有修改性函数均有一个参数为UndoManager类的指针。如果所传递的撤销管理器指针有效,则系统自动给出相配的UndoableActions可撤销操作,所执行的操作和撤销记录自动添加到UndoManager对象中。如果不使用undo功能,传递一个nullptr即可。

综上,可将ValueTree类的主要功能概括为4个方面:
 实现撤销/重做
 更简单的加载和保存数值
 集中保存不同类型的数据(对象)
 当数值变化时可产生回调

数据容器也好,数据模型也罢,归根到底都是为了读写和处理数据,从数据的来源、保存(数据进出)和操作处理这三个方面来分析,更容易理清思路。

获取数据:
 静态函数 fromXml() 读取XmlElement节点中的数据
 静态函数 readFromStream() 读取InputStream输入流中的数据
 静态函数 readFromData() 读取内存中的数据
 静态函数 readFromGZIPData() 读取内存中的ZIP压缩数据

保存数据:
 createXml() 将所有数据保存到一个XmlElement类的堆对象中
 writeToStream() 将所有数据以二进制方式写入OutputStream输出流对象

ValueTree的其他重要成员函数(网站发布,略)。