Skip to main content

复杂界面的模块划分

界面的模块划分

对于比较复杂的程序框图,最好把它划分为多个子 VI。这样,每个子 VI 都不会太复杂,可以大大提高程序的可读性和可维护性。对于界面来说,也是如此。如果一个界面过于复杂,最好也把它划分为多个模块。这不仅利于程序本身的编写维护,还可以方便用户使用和操作界面。

有些程序要求用户输入的信息非常多,比如,LabVIEW 的 "选项" 窗口就是如此(图 12.1)。这个窗口提供了 LabVIEW 中各种各样的设置信息,若是完全平铺在界面上,一个大屏幕也放置不下。而且,界面上的控件若是太多,用户也很难找到他所需的内容。因此,LabVIEW 选项界面把不同的设置按照功能的相似性,分成了若干组,每次只显示其中一组的设置信息。用户可以通过界面左侧的 "类别" 列表来选择显示哪一组的设置。

图 .1 LabVIEW 选项界面

再另举一个例子。比如 LabVIEW 中的导入共享库工具(图 12.2),用于把 DLL 文件中的函数都包装成 LabVIEW 的 VI。这一过程会要求用户提供比较多的信息,如 DLL 的文件名、生成 VI 的名字等。它与前面的例子面临相同的问题。若一次把这些设置都显示给用户,用户就无从下手了。导入共享库工具采用了与 LabVIEW 选项窗口稍有不同的解决方案。它使用了向导型界面来帮助用户操作。向导型界面与 LabVIEW 选项界面的区别在于,它通过 "上一步"、"下一步" 按钮来切换当前显示的配置。如果程序所需的各种信息或设置之间有先后依赖关系,那么采用向导型界面更为合适。

图 .2 导入共享库工具

前面介绍的两种类型的界面都有一个共同点,即把为数众多的控件按照相关性,分成多个组,每次只显示一组给用户,从而使程序界面变得清晰而且易于操作。

这两种界面在编程实现时,采用的也是类似的机制。唯一不同点是控制显示页面(即显示哪一组控件)切换的方式不同。一个可以任意显示出某个页面;另一个只能按顺序切换页面。

下面以向导型的程序为例,说明如何实现这类有多个页面的界面程序。

选项卡控件

向导型的程序有多个页面,每个页面上有表示不同含义的各种控件,这正适合于使用选项卡控件(图 12.3)。选项卡控件是一种在应用程序的设置对话框中非常常见的控件。它有多个卡片页组成,用户点击某一页对应的标签,控件就会把这一页的内容显示出来,而隐藏其它的卡片页。

图 .3 LabVIEW 中的选项卡控件

在设计向导型程序的时候,可以利用选项卡控件的这一特征,使向导程序各页与选项卡上各页一一对应(图 12.4)。把选项卡页面的标签隐藏起来,在程序中切换需要显示的页。

图 .4 某一向导型程序界面 VI 的前面板

图 12.4 是一个向导型程序在编辑状态时的界面。若拉大 VI 前面板的显示区域,就可以清楚地看出,这个 VI 前面板上首先放置的是一个大个的选项卡控件。其它用于程序运行时的控件都被放置在了选项卡的相应页上。

图 .5 切换显示页的程序框图

如果用户点击了 "下一步" 按钮,则在程序框图中通过设置选项卡的值,使其显示下一页面。(如图 12.5 所示。)

选项卡控件大大简化了程序界面的设计和编写,也方便了用户的使用。但是,它并不能显著地简化程序框图和改善程序的可读性和可维护性。这是因为即便使用了选项卡控件,用户所需要的所有控件还是全部被放置在了这个主界面 VI 上。对于这些控件的处理、包括对页面显示的控制代码全部都要在主 VI 上完成。对于比较复杂的界面,也许需要有十来个页面,那么前面板上所有的控件可能就会多达几十个。如果 VI 程序框图采用循环事件结构,也至少需要相应地处理几十个事件(图 12.6)。

图 .6 复杂界面的程序需要处理非常多的事件(本图中只列出了一部分事件)

对于这样的程序框图,别说读懂它的程序逻辑,就算是要找到某一个事件,也要一条一条查看一阵子才能找到。假如你打算在原有的向导中增加一个步骤,其工作量会大大超出你的预想。因此,若想提高程序的可读性、可维护性,除了把界面分页之外,处理它们的程序代码也必须分成模块才行。

子面板

子面板控件(图 12.7)在控件选板 "新式 -> 容器" 中。它可以在主界面 VI 中把另一个 VI 的前面板显示出来。使用子面板控件时,首先把它拖到主 VI 前面板上。它在前面板上看上去是一个透明的框。这个控件有些特殊,需要在 VI 程序框图上实现一些代码,才可以让它在主界面 VI 运行时,显示另一个子界面 VI 的前面板。

图 .7 空的子面板控件

为了演示这一控件,首先要创建一个子界面 VI(图 12.8)。等主界面 VI 运行之后,子面板控件会显示出这个子界面 VI 的前面板。

图 .8 子界面 VI 的前面板

接下来,要编写装入子面板的程序代码。同其它控件不同,子面板控件被放置在主 VI 前面板上时,在 VI 的程序框图中并没有一个与子面板控件相对应的接线端,而是出现一个它的调用节点。这个节点显示的方法是 "插入 VI"("Insert VI"),它的功能就是把另一个 VI 的前面板放到子面板控件中来。" 插入 VI" 的输入参数是那个需要被显示前面板的子界面 VI 的引用。因此,首先需要利用 VI Scripting 的函数和节点,打开子界面 VI 的引用,再把它传递给子面板控件的 "插入 VI" 方法(图 12.9)。此处还要注意两点:一,如果子界面的 VI 前面板已经被打开了,就无法再把它插入到子面板控件中,故必须关闭其前面板。二,在主界面上是需要观察和控制子界面的,如果子界面不运行起来,就无法完成相应的功能,所以需要运行子界面 VI。

图 .9 插入子界面的程序框图

主界面 VI 运行起来后效果如图 12.10 所示。在主界面 VI 中可以观察子界面的变化,也可以对子界面进行控制。

图 .10 子面板的效果图

回过头再来考虑一下上一节所提到的向导型应用程序界面的实现方法。它的主要问题在于主界面上控件太多,不便维护。现在借助于子面板控件,可以找到一条更为合理的实现途径:使用插件框架式程序架构来编写向导型的程序。图 12.11 是这种插件框架式程序结构的示意图。

图 .11 插件框架式的程序结构

插件框架式程序的实现思路是,把向导界面中的每个页面各自分配到一个独立的子界面 VI 上,这个页面上所有的操作,都由这个页面所在的子界面 VI 完成。图 12.11 左上部分就是为每个页面编写的子界面 VI。这些 VI 都被当作插件,在主程序需要的时候被调用并显示在主界面上。

图 12.11 右下角是主程序(主界面)VI。它前面板上最主要的区域是一个子面板控件,这个控件用于显示页面 VI 的前面板。在主程序需要显示向导中的某一步时,就把对应这一步骤的页面 VI 的前面板显示出来。这样就实现了向导功能。主程序的前面板上还有一些公共控件,比如 "上一步"、"下一步" 这样的按钮。这些按钮在所有步骤中都需要,所以可以放在主框架上,而不需要再在每个页面中重复了。

借助子面板控件搭建起来的插件框架式程序结构解决了复杂程序界面难以维护的问题。它把复杂界面划分为多个子 VI,每个子 VI 中的界面和代码都比较简单,非常容易阅读。这就大大简化了整个程序的维护工作。

但是,子面板仍然有一些使用不便之处。比如,需要编写一些额外的代码才能显示子界面;编辑状态下,看不到子界面,不利于界面调整;主界面与子界面 VI 之间,以及子界面 VI 相互之间的数据传递不是很方便;不方便把子界面作为一个公共模块发布给其它程序使用。

XControl

实际上,由于同一家公司开发的软件之间多少会有些相似,所以软件开发过程中经常需要把一些界面模块作为公共模块,提供给多个应用程序共享。要让不同的程序方便地使用同一界面模块,这个模块就应当像一个 LabVIEW 中自带的控件那样,可以直接被拖拽到 VI 前面板上;可以直接调整大小;可以方便地和程序中其它函数和控件进行数据交换。

可不可以把 LabVIEW 的自定义控件作为共享模块呢?答案是不行。使用自定义控件可以自行制作一个控件的外观,但是不能自定义它的行为。但是比较复杂的共享界面模块通常是需要一些自定义行为的。这种相对独立的、有特定界面和功能的模块称之为组件。比如,图 12.12 就是一个非常常用的组件。

图 .12 用于添加和管理一组路径的界面组件

这个组件是用来帮助用户选择并管理一组路径的。如果应用程序中需要用户输入一组路径,就可以直接使用这个组件。

这个组件的界面由以下几个基本控件构成:一个列表框(list box),用于显示所有路径;一个字符串输入控件(文本框),用于编辑某一路径;一个用于弹出路径浏览对话框的按钮;和四个用于添加、删除、以及调整路径显示顺序的按钮。

除了界面部分,这个组件还包括自定义的一些行为。最初,这个控件只是显示一组路径给用户,组件只使用列表框列出一组路径,用于编辑路径的文本框和浏览路径按钮是隐藏不见的。当用户用鼠标点击了列表框上的某一条路径,表示用户需要编辑这一路径。此时,组件需要把文本框和浏览路径按钮在鼠标点击的这一行显示出来,并使用这一行所显示的路径作为文本框的默认值,供用户编辑调整。还有其它一些行为:如,点击浏览按钮要弹出路径浏览对话框;点击向下移动按钮要使选中的路径向下移动一位等。

这个组件在程序中和外界的接口非常明确,是一个路径数组。它只要能够读写一组路径就可以了。

对于这样一个比较独立的组件,LabVIEW 提供了一个非常好的工具来制作它,这就是 XControl。也就是说,可以把上面提到的这个组件做成 LabVIEW 中的一个 XControl 控件。

LabVIEW 不但可以定义 XControl 外观,还可以定义它的数据类型和行为。XControl 可以如同 LabVIEW 自带的控件一样,在多个应用程序中共享或被发布给客户。并且也像普通控件一样,可以方便地被拖拽到 VI 的前面板上,然后使用其编程。