一种组态控件技术在电力监控系统中的运用
2022-01-07陈诚
陈 诚
(江苏斯菲尔电气股份有限公司,江苏 江阴 214400)
0 引言
目前市面上多数电力监控软件都提供了丰富的基础图元和符合电力系统符号标准的电气图元供现场施工人员绘制电力监控系统组态图,但是在非电气类复杂图元的提供上各有特色,操作方式和绘制复杂程度也各不相同。电力监控软件中,除高低压一次系统图包含大量电气图元外,更多的显示界面需要非电气类复杂图元来显示现场的设备运行情况,用于给运维人员提示,使其能够更好地查看了解现场系统运行状态。因此非电气类图元实现的好坏、操作的难易程度,对提升公司电力监控软件产品的竞争力有很大帮助。
Qt 作为源码级跨平台C++图形用户界面应用程序开发框架,被很多企业用于开发GUI 程序。其包含的GraphicsView 框架[1]结构主要包含视图类、场景类及图元类这3 个类,图形视图框架实现了模型-视图结构的图形管理,能对大量图元进行管理,支持碰撞检测,具有坐标变换、图元组合解组等多种方便的功能。其中,图形视图框架的QGraphicsProxyWidget 类为嵌入任何组件到场景提供了无缝支持,可嵌入简单的组件、复杂图元甚至是窗口。
采用Qt 图形视图框架的QGraphicsProxyWidget类可以深度整合电力监控软件中图元或控件特性,将多个图元、控件甚至是窗口组合成一个新的图元提供给用户使用[2]。这样可以很大程度上简化绘制组态图形的难度和步骤,降低用户的入门门槛,加快电力监控项目的实施。
1 窗口图元类
Qt 作为源码级跨平台的图形用户界面开发框架,非常适合有跨平台需求的电力监控软件开发,其QGraphicsProxyWidget 类是继承图元基类QGraphicsItem 的,而图元基类是抽象类,因此在子类中必须实现下面两个虚函数才能使用。
(1)boundingRect 函数。返回绘制图元的矩形边界,当需要图元接收到的操作事件时,这些事件只能发生在这个返回的矩形区域当中才会被接收到。
(2)paint 函数。使用QPainter 类绘制项目中一个具体的图元的内容。
将电力监控的软件组态图元分为基础图元、电气图元及窗口图元,它们关联的数据和表现形式不同,因此组态图元在程序设计时被分为两大类。基础图元和电气图元以QGraphicsItem 为父类,图元内容简单,以绘制基础图形和符合标准电气符号的电气图形为主。窗口图元则以QGraphicsProxyWidget为父类,图元内容复杂,可以包含Qt 提供的窗口控件或自定义复杂窗口。两类图元绘制的方式、操作方式是一致的,为了函数复用、简化编程、保证程序结构清晰,采用模板类。程序实现如下。
模板类没有实例化boundingRect 函数和paint函数,模板类还是纯虚类。其包含了两类图元的共有属性和方法,其中方法中定义多个虚函数,以方便子类重载实现多态性。
父类窗口图元继承于模板类,作为所有具有实际功能的子窗口图元的父类,其类型为QGraphicsProxyWidget 类,并包含所有窗口图元的公共属性和方法。
父类窗口图元实例化boundingRect 函数和paint 函数,其中boundingRect 函数返回绘制窗口的矩形范围,该矩形由图元保存记录。paint 函数必须实时计算当前窗口的尺寸,否则整个窗口图元不响应操作,只会呈现为默认大小状态[3]。具体实现如下所示:首先通过subWidgetRect 函数获取窗口图元的子窗口的大小,获取子窗口矩形后通过bottomRight 函数计算出右下角点的位置,如果当前窗口图元的子窗口的大小与窗口图元记录的矩形大小相比较超出设定的像素门槛,则重新计算子窗口的大小;其次,将其通过mapRectToScene 函数转换到场景类的坐标系中;最后通过setGeometry 函数重新设置窗口图元几何形状。这样就可以实现窗口图元保持用户拉伸操作后需要的大小。具体程序实现如下。
窗口图元同样需要对点击、移动、释放、双击等事件函数进行重载,否则图元将不会响应鼠标在场景中的操作事件。需要实现的函数如下:
因为QGraphicsProxyWidget 类最终继承于QGraphicsItem 类,所以事件重载函数需要调用QGraphicsItem 类对应的默认事件函数,否则窗口图元同样不会响应对应的事件操作。例如释放事件函数中最后需要加上下面的函数:
窗口图元在图片组态软件中绘制时的情况如图1 所示。从控件栏中选取需要的窗口控件,放置、拖拽拉伸后即可显示出相应图元的内容。窗口图元上有8 个方向控制方框,点击选中后按着鼠标可以向对应的方向拉伸,直到拖拽到需要的大小,同时最右侧的属性栏会实时显示出当前窗口图元的最新大小、坐标、角度等信息。
图1 窗口图元绘制
2 子图元窗口
父类窗口图元实现了图元的操作响应和几何形状计算,具体的样式和功能则需要通过继承的子类来实现。子类窗口图元有两种实现方式,一种是直接使用Qt 默认提供的一系列窗口控件,另一种是自己实现新的窗口控件。
Qt 提供了丰富的窗口控件,但是想直接在场景中调用显示Qt 的窗口控件是无法实现的,而通过窗口图元则可以直接使用Qt 提供的窗口控件,并且对应的窗口图元将具备控件本身的属性和相关操作,大大简化了编程工作量[4]。以创建按钮窗口图元为例,在构造函数中新建按钮控件,然后调用setWidget 函数将按钮控件嵌入,则绘制时对应的窗口图元就显示为按钮,此时操作按钮窗口图元就和正常使用Qt 提供的按钮控件没有区别,具有控件所拥有的操作和属性。
窗口默认情况下是提供边框和标题栏的,这样窗口图元看起来更像一个单独的窗口,为了让窗口图元呈现为与电气图元一样的外框以方便统一操作,需要将窗口图元的属性设置为Qt::FramelessWindowHint 无 边 框 窗 口,通 过setWindowFlags 函数进行设置。
Qt 提供的控件只能实现一些基础的窗口功能,如果想实现更复杂的窗口则需要自己编写新控件并嵌入到窗口图元。如果有需要,甚至可以将完整的窗口嵌入到窗口图元中以作为单一图元提供。如图1 所示,事件窗口图元包含了按钮、下拉框、表格等等控件,这里是将整个事件窗口包含在一个图元中。在绘制事件窗口时可以直接调用,无需施工人员再自己组合。同时,如果复杂控件中包含需要实时刷新的数据就必须重载paint 函数,并在函数中实现数据刷新函数,否则窗口图元是不会实时刷新控件上的内容的。
主要由窗口图元绘制的报表监控界面如图2 所示,界面中时间对话框、单选框、按钮都是直接使用Qt 提供的控件构成的窗口图元,它们可以使用控件本身的属性来实现各种操作[5]。表格是自定义的报表窗口图元,可以设置表格的样式并且自动地实时刷新报表中的数据。
图2 窗口控件组成的界面
3 结语
本文方法最终应用在江苏斯菲尔电气股份有限公司新开发的电力监控软件中,实现了图片组态软件中窗口图元的设计、编程及应用。该方法提供了大量复杂图元和控件,这些图元和控件为用户提供了成熟的绘制方案,无需用户自己组合拼接,降低了用户的入门门槛,可以方便用户快速掌握,减少培训成本,从而加快项目的实施,进一步减少时间成本和人力成本。