[喂饭]MVA-S01:用LabVIEW MVA框架丝滑搞定子面板与退出弹窗
⭐ VIP 极客会员专享

[喂饭]MVA-S01:用LabVIEW MVA框架丝滑搞定子面板与退出弹窗


导语
上期我们聊了专门开“UI解耦”的神器——MVA框架。文章发出去后台收到了一堆催更:“别光说不练,赶紧上菜啊!甚至有人让我变声直播讲解的”

今天我们就开始该系列连载的第一道硬菜。作为进阶路上的修仙者,你一定被LabVIEW原生的 “子面板(SubPanel)加载”和“点红叉叉退出程序时后台进程变僵尸” 毒打过。每多一个子面板,你就要写通知器的初始化,停止的事件注册,退出的释放。真的够了。

别慌,今天我们就在MVA的加持下,把这两个痛点按在地上摩擦。准备好你的鼠标,喂饭开始了!


一、 环境快速搭建

看过上期的读者相信已经搭建享受过了。

之后系列案例采用vip安装包的方式。关注【G 代码思维】之后,发送MVA获取到中文版vip安装包(由MDS大神封装)。

打开VIPM,点击工具栏的Shoe Menubar,将会显示菜单栏

image-20260309182821-g0snxkn.png

image-20260309182836-0r7yn71.png

image-20260309183040-tzw2wsl.png

image-20260309183201-tdbfstl.png

点击File>Open Package File选择composed_systems_lib_mva_framework-3.0.0.1.vip,选择Add To Library & Install进行安装

image-20260309183439-c3taspx.png

安装完成之后,点击点击Show in Palettes查看函数面板的位置,点击Show Examples可以查看附带的案例,环境搭建完成。


二、 MVA中常用的Actor角色有哪些?

image-20260309183745-qz5b8g7.png

1.Model Actor (模型) – 具有递归分层启动功能的业务逻辑 Actor
+ 模型启动后可发布数据订阅数据(中介者需要启动)
+ 模型可轻松实现为简单状态机或更接近传统命令模式的 Actor

image-20260309183811-fgn0w9w.png

常用的Vi为发布数据请求数据

image-20260309183946-qyck6fw.pngimage-20260309184018-2l46532.png

2.Viewable Actor (可视) – 可注入的静态或动态用户界面,同时是ViewManager 与ViewModel的父类

+ View的基础单元,具备事件注册与事件处理

+ 可以进行请求数据以及数据更新,但不能进行发布数据(那个是Model干的事)

image-20260309184553-5lsnij1.pngimage-20260309184607-383jzov.png

常用的Vi是注册控件事件请求数据

image-20260309184704-k1uqi6r.pngimage-20260309184712-u9k5vlg.png

下面的这一大堆是重写事件触发时使用的解析消息用的,功能其实都一样,看起来多而已。

image-20260309184728-t9kl6bv.png

3.ViewManager Actor (可视) – 界面管理
+ 插入 / 移除子面板
image-20260309185050-i61sf23.pngimage-20260309185102-amyz5dg.png

image-20260309185208-zgbntum.png

界面管理的事情是最多的,View和Model解耦之后,其行为相对是单一的。真正决定界面呈现效果的,基本都是ViewManager,时刻也有有意识ViewManager是Viewable的子类,能做Viewable的所有事情。

4.ViewModel Actor (视图模型) – 将可视行为与模型动作耦合、捕获 / 中继 UI 事件的组件
+ 作为顶级 (根) Actor,负责启动所有可视和模型分层结
+ 默认可捕获所有已注册的可视 UI 事件

image-20260309185547-e7y2aso.png

ViewModel干的事情非常少,常用的是构建MVA应用呈现以及发布数据

image-20260309185739-7w75a08.pngimage-20260309185746-36nxcs3.png

5.Mediator (中介) – Actor 之间的通信组件,尤其用于低耦合的可视组件通信
+ 传输抽象(与 Actor 或非 Actor VI 通信)
+ 订阅者指定的订阅策略(与中介者无关的订阅者)
+ 可选注入的具体 MediatorBusMonitor (中介者总线监控器) 用于应用调试

image-20260309185832-yoer1sd.png

几乎不需要编程,只在背后默默的进行数据订阅与发布。并且每一个主题的数据,都会自动加载一个Actor进行执行收发,不用担心主题之间冲突。


三、 创建两个Viewable,一个ViewManager以及一个ViewModel

3.1新建一个项目,保存为MVA子面板,右击我的电脑,新建库,保存为MVA-S01子面板

image-20260309190741-500z58e.png

3.2 右击库,再次新建三个库,分别保存到对应的文件夹下 Viewable ViewManager与ViewModel。

image-20260309201306-za6xgqg.png​​image-20260309192457-cwuzpgq.png

3.3 右击Viewable库,新建操作者,选择继承Viewable.lvclass(C:\Program Files (x86)\National Instruments\LabVIEW 2018\vi.lib\Composed Systems\MVA Framework\modules\mva-viewable\Source\IViewable\IViewable\IViewable.lvclass)第一次需要手动选择一下,后续直接Actor类型下拉选择了。命名波形图表_Viewable,存放路径为(..\MVA子面板\Viewable)

image-20260309201406-bs4f3lh.png

image-20260309191439-jqeikni.png

image-20260309192552-stq920k.png

image-20260309192601-wj8hrrh.png

image-20260309201526-5z7id73.png

3.4 右击波形图表_Viewable.lvclass,选择重写Actor Core,放入一个波形图表。右击波形图表,选择将控件匹配窗格

image-20260309201609-j9l3pqk.png

image-20260309202022-pmnild7.png

image-20260309202111-sq94mto.png

3.5 按照同样的方法,新建第二个Viewable,滑动杆_Viewable。第二次创建Viewavble就可以直接选择了。

image-20260309202424-8sor6fi.png

image-20260309202859-cl4p3cc.png

3.6 View_able暂时不需要进行操作了,开始创建ViewManager。方法类似,右击库ViewManager,新建操作者,选择基础ViewManager(C:\Program Files (x86)\National Instruments\LabVIEW 2018\vi.lib\Composed Systems\MVA Framework\modules\mva-viewable\Source\IViewManager\IViewManager),保存到ViewManager文件夹中,名称为上下双子面板_ViewManager。

image-20260309203627-e164hh1.png

3.7 同样重写Actor Core 开始设计Ui,先放个经典的垂直分割栏,关闭垂直滚动条。设置窗格位置,设置左侧。左侧用来放几个按钮来切换子面板。同样在右侧底部放个横向的分割栏,设置保持在底部

image-20260309203842-b282509.png

image-20260309204105-oyao26j.png

image-20260309204236-z4hsyfr.png

3.8 在中间与底部放上子面板,设置匹配窗格。命名为Main与Down,分别创建引用

image-20260309204525-83wa2kb.png

3.9 MVA Framework>Framework>Advanced>ProtectedSubpanel>下找到新建受保护子面板。输入子面板引用,输出捆绑到私有数据中。

image-20260309204558-lc3gq7d.pngimage-20260309204651-xsogt8a.pngimage-20260309204705-5ux4icj.png

image-20260309205151-sys2p8a.png

image-20260309205114-ykn0oxt.png

3.10 ViewManager的准备工作Ok了。现在我们来编写一个ViewModel,然后实现第一个功能退出。方法相同,鼠标右击ViewModel库,新建操作者,继承ViewModel(C:\Program Files (x86)\National Instruments\LabVIEW 2018\vi.lib\Composed Systems\MVA Framework\modules\mva-viewable\Source\IViewModel\IViewModel)。命名Main_ViewModel,存放ViewModel中。

image-20260309210021-jatc4m7.png

image-20260309210241-aiy6vii.png

准备工作完成,以上是让大家属性这几个操作者的创建方式,都非常的简单。


四、 退出与弹窗确认退出

现在我们来写退出。真正的来感受MVA框架的奇妙。

4.1退出的编写

不用写,已经自带了。

没错,不需要写退出,下面我们来写个Launcher来感受一下。

4.2 右击MVA-S01子面板.lvlib,新建Launcher单退出.vi

4.3在ViewModel面板中找到构建MVA应用程序

image-20260309210950-8h9j4re.png

4.4 左上角第一个输入就是刚刚写的Main_ViewModel.lvclass。

image-20260309211321-mi1j7td.png

4.5 第二个输入叫Startup View Configuration,这是个启动View的一个配置。这里我们直接拖动上下双子面板_ViewManager.lvclass

image-20260309211608-yfezvrw.png

4.6 第三个输入是Model,我们还没有写Model,直接右击创建常量即可

image-20260309211648-fc34esg.png

4.7 第四个输入是Mediator Type,这里我们来到Mediator面板中,拉第一个类。

image-20260309211801-vb83h4t.png

image-20260309211815-d8fqybf.png

4.8 拉取启动根操作者,然后在Viewable>Interface面板中,选择发生打开前面板消息,设置前面板启动位置与大小

image-20260309211909-ximvv2p.png

image-20260309212219-vt1u3hx.png

image-20260309220332-h616hxz.png

4.9 运行Launcher,弹出ViewManager界面,现在ViewManager是空的,我们还什么都没有配置。鼠标点击右上角关闭,自动退出,发现所有的Actor已经没有被占用的锁了,已经释放。

image-20260309214230-5g5il7k.png

image-20260309214247-u924zpe.png

4.10 如果我们想弹窗确认是否要退出怎么办呢?我们打开上下双子面板_ViewManager.lvclass的Actor核心,在Viewable>Event>中,选择注册VI事件,输入Vi引用与选择前面板关闭?事件

image-20260309214427-efgmi5z.png

image-20260309214628-5gp4ugc.png

4.11 右击Main_ViewModel.lvclass,选择重写接收面板关闭事件

image-20260309215230-ca2kqs5.png

image-20260309220419-asv81bk.pngimage-20260309220358-m3be51o.png

默认保存之后,再次运行Launcher,就会有弹窗确认。

image-20260309215426-vjqrq5j.png

优雅的停止已经Ok了,这个地方其实是MVA框架的一个问题,框架默认了关闭前面板是直接执行的。进阶的我们其实可以重写该事件过滤器Filter,感兴趣的可以自己探索,也可以私信我,这个部分后面涉及到的时候集中讲,此处讲还为时过早。

image-20260309220739-e3jwpyg.png


五、 子面板切换

5.1 我们现在开始实现子面板切换业务,首先我们需要先继续完善上下双子面板_ViewManager.lvclass的Actor Core,放上两个按钮

image-20260309221411-46znpqs.png

5.2 选择控件注册事件vi,输入引用数组与选择值改变

image-20260309221534-2shbkhj.png

image-20260309221637-dwkvo28.png

5.3 右击上下双子面板_ViewManager.lvclass重写接收到值改变事件

image-20260309221754-ormvjh9.png

5.4在Evcent面板中,选择Unpack Valyue Change。在MVA框架中,注册的事件触发的时候会自动发送消息到对应的vi中,因为不同的消息内容不同,需要使用不同的解包vi

image-20260309221843-q9y7z4n.png

5.5 根据Unpack Valyue Change输出中的Label可以区分是哪个按钮触发的,将数据进行值更新,选择值更新Vi

image-20260309222333-r2sd2t9.png

image-20260309222747-7qsl7sv.png

image-20260309222806-zfbzakd.png

5.6 这里的值更新之后,ViewModel就可以监测到,然后进行发布,我们需要右击Main_ViewModel.lvclass重写捕获嵌套值更新。

image-20260309222950-vz5yq6o.png

5.7 在重写的Vi中,我们需要解包这个消息,但是没有快捷的vi,有两个办法,一是复制案例里面ViewModel中解包簇。第二种是右击Nested Value Update Msg显示类库,选择该消息类下的Unpack Nested Value Update.vi

image-20260309224519-5oce305.png

image-20260309224614-vicpf3x.png

image-20260309224645-baajypb.png

5.8 Ok了,下面我们开始编写Launcher子面板切换.vi,先把之前退出的启动器内容复制过来,然后选择写入启动视图与组装绑定视图管理器,组装绑定视图管理器是静默启动,把需要呈现的界面都进行捆绑加载,要有对应的名称,这个名称与刚刚按钮触发时标签名称对应,这个静默启动器的名称与主题名称对应。

image-20260309224942-vasun4b.pngimage-20260309225017-bsffcg4.png

image-20260309225040-a5up6w2.png

image-20260309225738-meh0gi9.png

5.9 我们现在配置了Whrite Startup Views,把全部静默启动的Viewavble命名为Main,我们之前建立了子面板,还没有为其进行分配Main是插入到那个子面板,需要右击上下双子面板_ViewManager.lvclass重写初始化前面板

image-20260309230328-e0sjzmp.png

5.10 使用读取前台的可查看消息队列进行解包现在加载的Viewable的引用与名称,如果插入的是Main名称的Viewable就放入到Main Subpanel中

image-20260309230711-7uf4way.png

image-20260309230910-azn1f8n.png

image-20260309230949-sfmfgyr.png

5.11 Down Subpanel暂时还用不到,后面我们进行状态栏显示再使用。如今子面板切换功能已经完成。运行Launcher看看吧。

image-20260309231457-xalaw0j.png

image-20260309231446-ceuj5al.png


🎁 本期福利与下期预告

看到这里,脑子里是不是已经有画面了?但光看没用,得练。因为这个是一个全新的框架,我讲的非常的细,下一期很快就会来。

老规矩,纸上得来终觉浅,绝知此事要跑码。我们为大家准备了今天讲的 【MVA子面板切换与退出源码】 。代码不仅跑得通,还在关键节点加了保姆级的中文注释。

📢 获取方式
关注微信公众号:「G 代码思维」,在后台发送暗号: 【MVA子面板】 ,即可原版源码压缩包。

下一期,我们将开始接触MVA的核心魔法:发布-订阅(Pub/Sub)机制。当子面板里的按钮按下去,主界面上的图表是怎么自动刷新的?

点个【赞】和【在看】 ,咱们下期继续喂饭!

🔒
⭐ VIP 极客会员专享

试读已结束,解锁完整内容与工程源码

本文包含 LabVIEW MVA 框架完整实战源码包、架构逻辑导图与核心技术细节。升级会员即可解锁全站 VIP 专栏!

解密完整项目工程源码 (包含 `.lvproj` 资源)
解锁高分清 MVA 架构流程图与原理剖析
⭐ 开通 VIP 年卡 (仅 ¥99/年)