你我山前没相见,山后别相逢
一、 前言
最近做的一个项目需要用到拖拽控件的功能,就在网上查了下资料,发现需要用到LabVIEW的动态注册事件模块,之前没有接触过这方面的东西,学完以后还是决定写下来防止以后忘记,有谬误的地方还望各位批评指正!
对LabVIEW比较熟悉的人应该都用过事件结构,事件结构是一种非常有效的交换数据方法,通过用户自定义的事件,可以在不同的线程中传递数据。但是事件结构有一个先天弊端,就是自定义的事件在程序运行的整个过程中都会被触发,比如按钮点击事件,只要按钮被点击了,那么对应事件结构中的程序就会执行。
此时如果我想设置一个开关,只有这个开关打开的时候,再点击按钮才会触发事件结构;如果开关关闭,无论何时点击按钮,都不会触发任何事件结构。这种情况下,普通事件结构是做不到的,就需要用到我们前面提到的动态注册事件。
由于鼠标移动类事件是连续发生的,容易发生消息阻塞,造成CPU的占用率显著提升,使电脑的运行变得卡顿,使用动态注册事件可以有效地减少消息发送的数量,减小CPU的负担。
这里找到的事件结构与“编程”--“结构”中普通的事件结构没有多大的区别,主要是多了一个“动态结构接线端”,如下图2中红圈所示,这个接线端跟移位寄存器一样,也是成对出现的,但是只能用在事件结构中。由于普通的事件结构用不到这个功能,所以默认是不显示这个接线端的,鼠标右键事件结构框也可以把这个接线端显示出来。 图2 动态结构接线端
这个动态结构接线端主要的作用就是进行动态注册事件的,下面我将把我在网上整理的资料包括我自己理解,做成两个实例与大家交流一下,方便大家更好地理解动态注册事件 。
二、 实战练习
我的开发环境:Windows10(64bit)、LabVIEW2017
(1)实例1:自由控制前面板控件上下移动
先放上实例1的前面板,再来说下这个实例具体要实现什么功能: 图3 实例1前面板在前面板上放置一个三角形的装饰块,点击“上升”按钮,三角形往上移动一点,点击“下降”按钮,三角形就往下移动一点;再点击一个“取消注册”按钮后,“上升”按钮和“下降”按钮全部失效;接着点击一下“注册事件”按钮,“上升”按钮和“下降”按钮又可以控制三角形上下移动。我们来看下实现的程序: 图4 实例1程序面板
从上面的程序可以看出:
a)在while循环外面,我提前注册了两个动态事件结构,分别是“上升”和“下降”事件;所以程序运行后,点击“上升”按钮和“下降”按钮就可以直接控制三角形装饰块的启动。
c)可以在“窗格”(服务器引用)--“修饰”(前面板属性节点)中拿到三角形装饰块的引用,因为从“修饰”(Decoration[])出来的是引用数组,你拖拽到前面板的第一个装饰索引为0,第2个装饰索引为1,以此类推;故要索引数组。
e)细心的小伙伴可能已经发现了一点异常,动态注册的“上升”、“下降”在事件结构的事件选择器中是用单书名号括起来的,而普通的事件用的都是用双引号。这就是动态注册事件和普通事件的区别,我们随意选择一个事件结构,右键事件结构选择器,在弹出的菜单中点击“编辑本分支所处理的事件”,你会看到下图7: 图7 编辑事件页面
从上图可以看出,红色方框“动态”下面就包含两个单书名号的注册事件<上升>和<下降>,这就是我之前注册好的2个事件;当然,底下“控件”栏所包含的就是普通的事件,它包含上升按钮和下降按钮以及其他按钮的事件。
这个时候就有个问题:在事件编辑页面,一个按钮既有动态注册的事件,也有默认的普通事件,那么在写程序的时候,是不是可以同时使用呢?
答案是肯定的,我在上述程序里尝试添加上升按钮和下降按钮的普通事件,程序没有报错;只是添加普通事件后,对应按钮的注册事件只能运行一次,而普通事件的功能是正常的,不受任何影响。这也许说明同一个控件的普通事件的运行优先级要高于其对应的动态注册事件,所以,我们在使用动态注册事件结构的时候,就不要在程序中使用同一控件的普通事件,以避免注册事件失效。
f)程序运行结果 图8 实例1运行结果
(2)实例2:鼠标拖拽控件
实例2的具体功能就是,当程序运行时,可以用鼠标随意拖拽页面上的控件,比如按钮、数值显示框等。
通过程序面板我们可以看到,在while循环外先注册了3个事件,分别是鼠标按下?、鼠标移动、鼠标释放;然后就是对应的事件结构。
a)“鼠标按下?”和“鼠标释放”事件对应的注册对象是“控件”,鼠标移动事件对应的注册对象“窗格”句柄,这个句柄是怎么来的?通过创建“服务器引用”-选择“窗格”-右击“窗格”引用,点击“创建输入控件”得到,也就是将下图中的VI服务器引用创建输入控件得到。这个通用的窗格引用句柄起到也是一个初始化占位的作用。
b)“控件”被鼠标按下时,通过“控件引用”来得到具体是鼠标按下的哪个控件,并将其送给移位寄存器;同时通过“坐标”获取对应控件的坐标值,并将其送到对应的移位寄存器中。
c)在“<窗格>:鼠标移动”事件中,通过“坐标”先得到鼠标的实时坐标值,然后将鼠标的坐标值与被按下控件的坐标值求和,再赋值给控件的坐标属性,控件获得新的坐标值就会移动,最后把新的坐标值送到控件的移位寄存器中,进而起到拖拽控件的效果。
d)同理,在“<Controls[]>:鼠标释放”事件中,使用一个非法引用句柄常量,对鼠标移动事件进行取消注册,如此,鼠标释放后,控件就不会再随鼠标移动了。
网友评论