2.1.2 界面设计
界面设计就是使用图形组件类库中的图形组件类,按照数控系统的实际需要构建界面的过程。由于根据数控系统的特征自定义了各种图形组件类并构成了相应的类库,因此在构造界面时只要从类库中选择合适的图形组件类,并设置相应的属性即可。此过程是通过将图形组件类库链接到QT的Designer中,使用户拖拽相应组件实现的,设计完成后保存即可生成ui文件[3]。
这对类库的设计也提出了要求,必须尽可能的丰富图形组件类库,以满足各种用户的不同需要,使其可以方便快捷的使用类库中的图形组件定制自己的界面。同时要为类库设计相应的接口,以使当类库中的组件不能满足用户要求时,用户可以通过接口函数将自定义的类添加到组件类库中。
2.1.3 脚本程序实现
脚本程序是对界面设计所得到的界面进行脚本编程,实现界面的动作,完成界面的功能定制。由于脚本语言具有语法和结构比较简单、良好的快速开发、高效率的执行等特性,并且它可以把服务组件粘合起来,因此被广泛用于GUI创建当中,所以本设计中也采用脚本程序实现定制界面的开发。当然这也要求用户必须具有一定的脚本编程能力,对用户来讲是一个额外的负担,但为了设计出良好的界面系统,用户是能够接受的。
编写的脚本程序是逐级嵌套的,如果界面只是由简单的图形组件构成,则脚本程序的编写较简单,直接对界面编程即可。否则对于含有复杂的图形组件类的界面,其脚本程序的编写是一个逐级嵌套的过程,先对底层的组件类(内嵌的界面)编写脚本程序,再对上层的组件类编写脚本程序,并且上层脚本程序的功能需要调用下层脚本程序来实现。正是由于脚本编程的这种嵌套关系,对于自定义图形组件类的粒度提出了要求。如果在自定义图形组件类时粒度比较大,例如可以把显示坐标位置的界面封装成一个类,这样用户在编写脚本程序时就可以直接调用这个类来显示位置信息,程序比较简单,但是这样留给用户的自由空间就比较少,难以让用户完全按照实际需要设计自己的界面系统;反之,如果粒度比较小,则留给用户的自由空间就比较大,使其可以按照自己的意愿组织设计界面,但是这也要求用户编写复杂的脚本程序实现这些功能,加重了用户的负担。本设计中为了解决此问题,采取尽量兼顾的办法,例如显示位置坐标的界面,通常有三轴和六轴,因而我们将这两个界面单独封装成类以方便用户使用;同时我们也将单个的轴封装成类以给用户充分的自由。
2.2 定制QT界面加载器并为脚本引擎添加对象及属性
2.2.1 定制界面加载器
本设计使用QT的QUiLoader类加载界面,它提供的功能函数集使得我们可以在程序运行时根据ui文件中的信息动态的加载界面。界面加载器加载界面的流程如图3所示。
图3 界面加载流程图
当界面中的图形组件都是QT的内置类型时,可以使用QUiLoader类直接加载界面,将ui文件以字符流的形式读入,根据其中的信息调用类中的createAction()、createW idget()等虚函数生成相应的动作和图形组件,实现界面加载。如界面中含有自定义的图形组件时,就不能直接使用QUiLoader类加载,而需要通过继承派生出专用的加载器类并重新实现其中的虚函数使其能够根据ui文件中的信息,调用在界面设计过程中所封装的图形组件类的构造函数,生成定制界面。
如在设计模拟刀具轨迹的界面时,在界面中使用了自定义的Plotter图形组件,则需要为其定义专用界面加载器来加载该界面。代码如下:class PlotterUiLoader: public QUiLoader//定制的界面加载器函数。{
public:
PlotterUiLoader(QObject* parent=0): QUiLoader(parent)
{} //构造函数
VirtualQW idget* createW idget(constQString&className,
QW idget* parent=0, constQString&name=QString()) {…} //在其中调用Plotter的构造函数创建界面组件,完成加载任务
}