用 LabVIEW 编写 Wizard 类型的应用程序 3 (LabVIEW 8.0)

五、SubPanel

    主VI太过复杂,是肯定会影响它的可读性和可维护性的。所以,对向导类型程序的进一步改进的重点,就是把主VI进一步模块化,不但是程序代码要模块化,界面也必须模块化。代码模块化相对比较简单,多利用子VI就是了。但是界面的模块化,在之前的LabVIEW中是非常困难的,因为 LabVIEW 没办法在运行时,把不同的 VI 的界面拼在一起。是 LabVIEW 7.1 和 8.0 的一些新功能最终解决了这个问题。

    对程序界面模块化,按一般的思路,第一步就是把每个页面划分成一个独立的模块。这似乎又回到了我们前文提到过的第一、二个阶段。但有所不同的是,旧版本 LabVIEW 功能不全,无法很好的管理被分为模块的页面,而新 LabVIEW 改进的对这方面的支持。
    在 LabVIEW 7.1 中出现了一个新的控件 – SubPanel(子面板)。当一个 VI 运行的时候,它的 SubPanel 控件中,可以显示另一个 VI 的前面板。我们可以利用这个新的控件,我们可以使用插件框架式程序架构来编写向导型的程序。图1是这种插件框架式程序结构的示意图。


图1:插件框架式的程序结构

    插件框架式程序的实现思路是,把向导的每个页面都分配到一个独立的VI上去,这个页面上所有的操作,都有这个页面所在的VI完成。图1左上部分的那些 VI 就是为每个页面编写的VI。这些 VI 都被当作插件,在主程序需要的时候被调用显示在主程序上。
    图1右下角的VI是主程序的 VI。它的界面上主要是一个 SubPanel 控件,这个控件用于显示页面VI的界面。主程序在每一步的时候,分别把对应这一步骤页面的VI的界面显示出来,这样就实现的向导功能。主程序的界面上还有一些公共控件,比如“上一步”“下一步”这样的按钮,这些按钮在所有步骤中都需要,所以可以放在主框架上,不需要再在每个页面中重复了。

    这样的插件框架式程序在运行时,主VI和插件VI是在同时运行的。
    主 VI 的运行流程大致如下:创建或注册程序运行时需要的各种事件 -> 初始化程序 -> 等待和处理事件,主要是管理插件。比如在用户按下“下一步”按钮后,主程序负责把当前的插件移出内存,把对应下一页的 VI 调入内存,运行,并显示界面。 -> 最后负责销毁创建的事件,关闭所有资源,退出。
    插件 VI 的主要程序结构和主 VI 一样,采用的是事件处理结构。它在运行起来以后执行的流程也和主 VI 类似: 创建或注册插件运行时需要的各种事件 -> 初始化程序 -> 等待和处理事件,主要是用户在界面上的操作,和一些后台程序,比如数据处理等等。 -> 销毁创建的事件,关闭插件。

    虽然 SubPanel 在 LabVIEW 7.1 中就出现了,但是我当时却并没有在我的程序里采用上述的设计方案。只是因为当时还有一个棘手的问题没有解决。这个问题就是 VI 太多了,不好管理。
    向导页面的多个插件 VI,他们的功能有很多共同之处。在以前,所有页面都在同一个主 VI 中的时候,那些相同的功能可以通过调用同一个子 VI 来完成。但是,把页面分割成独立 VI 之后,很多情况,我都不得不为每个页面做一整套子 VI,他们在每个页面上完成的功能都类似,但却不能使用同一个子 VI。
    以处理事件为例,我写了一套子 VI 处理页面 VI 的事件。但是由于不同的页面可能会同时在运行,每个页面都有自己的事件,如果调用同一套处理事件的子 VI,不同页面之间会相互干扰。
    另外,如果想创建一个新的页面,最方便的方法莫过于把一个已有页面的 VI、子 VI 全部复制一遍,然后在其基础上做改动。LabVIEW 以前是不允许出现同名 VI 的。把一个页面的 VI、子 VI 全部改名,还要保证调用链接不出现混乱,非常的不方便。所以上述的插件框架方案是我等到到 LabVIEW 8.0 出来以后才开始使用的。

六、Project Library

    LabVIEW 8.0 作为一大升级版本,拥有了很多新特性。其中之一是“Project Library(工程库)”。
    工程库是一组功能相关联的VI或其它文件的集合。一个工
程库是把一组功能相
关的VI,和其她文件按一定结构组合封装在一起,以便于代码的管理和发布。工程库的名字也是库中VI的名字空间(name space)。这个名字空间
与C+
+、C#等语言中的名字空间的概念类似。有了它
LabVIEW 就可以在一个程序中使用两个同文件名的 VI,当然,它们的名字空间不能相同,也就是它们存在于不同的工程库中。
    另外,工程库中的 VI 有操作安全设置, 每一个 VI 可以被设置为公有(Public,可以被库外的VI调用);或者私有(Private,只能被库的成员VI调用)。

    工程库给开发插件框架式的程序带来的很大的方便,特别是在 VI 文件的管理方面。
    新的设计思路是这样的:把所有的功能模块都封装在工程库内,比如说每个页面都有一个对应的工程库。专为这个页面使用的所有子 VI 都被加在它的工程库内。并且,不想被其它库使用的的子 VI 都要标记为私有。被这样组织起来的程序,虽然 VI 数量还是很多,但模块划分清楚,不会出现不希望出现的调用关系。安全性,可维护性就大大提高了。
    另外,可扩展性也得到了提高。如果需要添加一个新的页面,只需要把一个已有页面复制一份。复制出来的这一份,只要工程库的名字换个新的就行了。再也不需要一个一个的去改VI的名字了。
    图2是我的一个程序的工程管理窗口:


图2:采用工程库管理程序的VI

    但是,现在的程序结构还是有些令我不太满意的地方-重复的代码太多。不同页面之间,有很多类似的VI。就比如图2中的程序,每个页面都会用到事件处理的一些 VI,他们的代码在每个页面中都是相同的。但是,利用这个工程库组织起来的程序却不能把这些重复的VI提取出来,变成共用的子VI,因为在每个页面里,这些代码相同的VI,处理的数据是不同的。并且这些数据会保留在 VI 的局部或全局变量中,不同的页面如果共用一套子VI,会相互影响,出现数据混乱的。
    直到 LabVIEW 支持了面向对象的编程之后,我们才终于找到了一个完美的解决这一问题的方案。

阮奇桢

《我和 LabVIEW》
 用 LabVIEW 编写 Wizard 类型的应用程序 1 (LabVIEW 6.1 之前)
 用 LabVIEW 编写 Wizard 类型的应用程序 2 (LabVIEW 6.1 ~ 7.1)

Advertisements

6 thoughts on “用 LabVIEW 编写 Wizard 类型的应用程序 3 (LabVIEW 8.0)

  1. Pingback引用通告: 博客版《我和LabVIEW》目录 « 凡人琐忆

  2. 4 打不开是因为我写到这里时思路发生了变化。后来就没有再按照原定的计划写了。第四部分打算写的是XControl+OOP。我后来的其他一些文章对这两部分有简略的介绍,书里写的更详细一些其他。

  3. 很期待阮先生的“用 LabVIEW 编写 Wizard 类型的应用程序 4”,可惜博客上打不开,不知道阮先生的新书中是否包含这部分类容?

  4. 这个文章下一篇就是写如何利用 LVOOP 改进向导程序的架构,但是还一直没时间开始写呢 ^_^*

  5.  你的文中说:“现在的程序结构还是有些令我不太满意的地方-重复的代码太多。”“直到 LabVIEW 支持了面向对象的编程之后,我们才终于找到了一个完美的解决这一问题的方案。”完美方案是指现在你写的方案吗?

  6. 个人感觉使用subpanel调用起来速度有点慢,而且画面很容易出现错位.
    我一开始也想这样做,后来放弃了,最后改用TAB CONTROL做了,所有的画面都在不同的页面上做,程序里在不同的tab嵌入不同的子程序(子vi不显示其前面板). 感觉这样速度快多了,而且在不同的步骤间传递数据起来也很方便.
    很想知道你这个程序的反应速度怎么样,还有就是wizard在不同页面之间如果需要传递一些数据是怎么实现的呢?最后就是使用面向对象的编程方法,很想学习下.希望能把代码开放下,让我学习学习.~
    期待ing…..

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s