kanzi多工程属性绑定问题

文章讲述了在实际项目中,如何通过创建PluginDataSourceGlobal插件,利用Kanzi的数据源机制实现主工程与子工程之间的属性绑定,解决预设件间及工程间的通信问题,简化了全局变量访问和属性管理。
摘要由CSDN通过智能技术生成

背景:实际项目中,架构组成是一个主工程,多个子工程,主工程通过Prefab View 2D|Prefab Placeholder 2D引用子工程预设件。
多个工程之间直接无法消息互通,比如子工程想绑定主工程某节点某属性,或者子工程内不同预设件间属性绑定,用别名或者相对路径都会发生kanzi爆红报错(如果子工程创建同名属性,外加别名方式,可以解决爆红报错。但是要额外创建属性和别名,不方便),而且如果节点改动,又要重新改相对路径,十分的不方便。
为此,我设计了插件PluginDataSourceGlobal,利用datasource机制实现全局变量访问。

1. 创建插件

参考使用kanzi开发仪表HMI插件

2. 搭建多工程环境

新建子工程UntitleTest,UntitleTest2,并引用kanzi 案例XML_data_source的插件,并设置xml。DataSource插件使用参考官方本地文档即可。

在这里插入图片描述
主工程结构
在这里插入图片描述
在这里插入图片描述

子工程1结构
在这里插入图片描述

子工程2结构
在这里插入图片描述
xml内容
在这里插入图片描述

3. 设计插件

3.1 NodeRefByStringProperty

NodeRefByStringProperty属性用来绑定带有Data Context属性的节点,一般是主工程RootPage

3.2 TestIntProperty

TestIntProperty属性用来更新datasource值

3.3 时序

在这里插入图片描述

4. 实现插件

更新datasource方案,参考kanzi 3.9.8 DataSource动态预览

void PluginDataSourceGlobal::onNodePropertyChanged(kanzi::AbstractPropertyType propertyType, kanzi::PropertyNotificationReason reason)
{
    if (NodeRefByStringProperty == propertyType) {
        kzLogDebug(("NodeRefByStringProperty = {}", getProperty(NodeRefByStringProperty)));
    }
    else if (TestIntProperty == propertyType) {
        kzLogDebug(("TestIntProperty = {}", getProperty(TestIntProperty)));
        string str = getProperty(TestIntProperty);
        handleIntInput(str);
    }
    Node2D::onNodePropertyChanged(propertyType, reason);
}

TestIntProperty变化后调用handleIntInput更新对应的datasource,这里只演示了int类型。

void PluginDataSourceGlobal::handleIntInput(std::string value)
{
    int index = value.find("=");
    if (index >= 0) {
        string name = value.substr(0, index);
        string valuestr = value.substr(index + 1, value.size());
        int val = Str2Numberi(valuestr);
        kzLogDebug(("TestIntProperty Name={}, value={}, v={}", name, valuestr, val));

        if (m_lastDataSourceName == name && m_destObjectInt) {
            //if (!m_destObjectInt) return;
            if (val != m_destObjectInt->getValue()) {
                m_destObjectInt->setValue(val);
            }
            return;
        }
        m_lastDataSourceName = name;        

        NodeSharedPtr node = lookupNode<Node>(getProperty(NodeRefByStringProperty));
        if (!node) return;

        const ResourceSharedPtr root = node->getProperty(DataContext::DataContextProperty);
        if (!root) return;

        DataContextSharedPtr data = dynamic_pointer_cast<DataContext>(root);
        m_root = data->getData();
        if (!m_root) return;

        std::shared_ptr<DataObjectInt> p = m_root->lookupDataContextOfType<DataObjectInt>(name);
        m_destObjectInt = p.get();
        if (!m_destObjectInt) return;
        if (val != m_destObjectInt->getValue()) {
            m_destObjectInt->setValue(val);
        }
    }
}

这个函数就是查找datasource,然后设置新值。
举例:gauges.battery=10,把=裁切后,获得datasource标签gauges.battery和新值10,这里做了一个优化,备份DataObjectInt,不用每次查找。

5. kanzi使用插件

子工程untitledTest,点击按钮,设置临时属性NewPropertyType
插件绑定属性TestIntProperty=

"gauges.battery=" + STRING({@./UntitledTest.NewPropertyType})

子工程untitledTestuntitledTest2,Text Block 2D各自绑定

"Test1 Result=" + STRING({DataContext.gauges.battery})
"Test2 Result="+STRING({DataContext.gauges.battery})

主工程使用子工程预设件

6. kanzi演示

请添加图片描述

7. vs debug演示

请添加图片描述

8. 总结

这个方案能够很简单的解决预设件之间,工程之间属性绑定问题。
可以方便的拓展float,string等类型。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值