本项目对设备的监控有四种视图模式,能够任意切换,数据监控、地图监控、设备监控、曲线监控,其中数据监控是最经常使用的,因此在主界面导航中也排在第一位,综合观察分析了不少气体安全或者组态监控软件,大部分用户习惯都是有个表格一行行显示对应设备的实时数据和状态等,加上一些特殊的颜色标识,这样显得更直观,有时候还会分门别类展现。node
Qt提供了表格控件QTableWidget,能够直接以行列的形式展现数据,使用接口和方法也是很是友好,直接new一个QTableWidgetItem而后指定行列位置setItem便可。通常在系统初始化的时候经过读取数据库中的设备列表实例化item而后加载,难点在于如何动态更新这些数据,并根据收到的值以不一样的颜色显示,为此还专门写了一个方法setColor来对传进来的数据进行过滤,好比报警的值红色加粗显示,这些颜色还特地作了自定义,能够在系统设置中分别设置低报、高报、离线、正常等各类颜色。mysql
在协议解析的类中,并非收到数据就立马发送到数据表格中,那样刷新频率太大,没有意义也没有必要,由于绝大部分时间的数据实际上是不变的,因此在协议解析的类中,有一个队列专门存储的每一个设备对应的值,只有当值发生了变化,才须要从新发送到界面进行展现,设备上线下线也是一样的处理,只有当设备首次上线或者离线的时候,才须要去更新状态。linux
皮肤开源:https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo 文件名称:styledemoc++
体验地址:https://gitee.com/feiyangqingyun/QWidgetExe https://github.com/feiyangqingyun/QWidgetExe 文件名称:bin_sams.zipgit
void DeviceHelper::deviceValue(const QString &positionID, float value) { //下面的不会被频繁执行,只有数据变更了才会执行,已经在解析的地方作了过滤 //处理设备面板 if (App::PanelMode == 0) { foreach (frmDeviceNode *device, devices) { if (device->getPositionID() == positionID) { device->setValue(value); break; } } } else if (App::PanelMode == 1) { foreach (frmDeviceNode2 *device, devices2) { if (device->getPositionID() == positionID) { device->setValue(value); break; } } } //处理设备按钮 bool alarm = false; foreach (ButtonDefence *btn, btns) { if (btn->property("positionID").toString() == positionID) { alarm = (btn->getButtonStatus() == ButtonDefence::ButtonStatus_Alarm); btn->setProperty("value", value); //有两个传感器 是开关量 数值是 一、2 显示时 用正常 和异常代替 QString nodeType = btn->property("nodeType").toString(); if (nodeType == "SJ-0001" || nodeType == "JG-0001") { btn->setText(value == 1 ? "正常" : "异常"); } else { btn->setText(QString("%1 %2").arg(value).arg(btn->property("nodeSign").toString())); } break; } } //处理设备表格 int count = deviceData->rowCount(); for (int i = 0; i < count; i++) { QString id = deviceData->item(i, 1)->text(); if (id == positionID) { deviceData->item(i, 7)->setText(QString::number(value)); break; } } } void DeviceHelper::deviceAlarm(const QString &positionID, quint8 alarmType) { //0-浓度上限报警 2-浓度下限报警 5-其余报警 bool alarm = (alarmType == 0 || alarmType == 2 || alarmType == 5); //处理设备面板 if (App::PanelMode == 0) { foreach (frmDeviceNode *device, devices) { if (device->getPositionID() == positionID) { device->setAlarm(alarm); break; } } } else if (App::PanelMode == 1) { foreach (frmDeviceNode2 *device, devices2) { if (device->getPositionID() == positionID) { device->setAlarm(alarm); break; } } } //处理设备按钮 foreach (ButtonDefence *btn, btns) { if (btn->property("positionID").toString() == positionID) { btn->setButtonStatus(alarm ? ButtonDefence::ButtonStatus_Alarm : ButtonDefence::ButtonStatus_Arming); //切换到当前地图 initDeviceMapCurrent(btn->property("nodeImage").toString()); break; } } //处理设备表格 int count = deviceData->rowCount(); for (int i = 0; i < count; i++) { QString id = deviceData->item(i, 1)->text(); if (id == positionID) { setColor(deviceData->item(i, 7), deviceData->item(i, 9), alarmType); break; } } //云端数据同步 if (App::UseNetDB) { int nodeStatus = 1; if (alarmType == 0) { nodeStatus = 3; } else if (alarmType == 2) { nodeStatus = 2; } else if (alarmType == 5) { nodeStatus = 5; } QString sql = QString("update NodeData set NodeStatus='%1' where PositionID='%2'").arg(nodeStatus).arg(positionID); DbTcpClientThread::Instance()->append(sql); } } void DeviceHelper::setColor(QTableWidgetItem *itemValue, QTableWidgetItem *itemStatus, quint8 alarmType) { //0-低报 1-低报恢复 2-高报 3-高报恢复 5-其余报警 6-其余报警恢复 if (alarmType == 0) { itemValue->setForeground(QColor(App::ColorLimit)); itemStatus->setForeground(QColor(App::ColorLimit)); itemStatus->setText("低报"); } else if (alarmType == 2) { itemValue->setForeground(QColor(App::ColorUpper)); itemStatus->setForeground(QColor(App::ColorUpper)); itemStatus->setText("高报"); } else if (alarmType == 1 || alarmType == 3 || alarmType == 6) { itemValue->setForeground(QColor(App::ColorNormal)); itemStatus->setForeground(QColor(App::ColorNormal)); itemStatus->setText("正常"); } else if (alarmType == 4) { itemValue->setForeground(QColor(App::ColorZero)); itemStatus->setForeground(QColor(App::ColorZero)); itemStatus->setText("离线"); itemValue->setText("0"); } else if (alarmType == 5) { itemValue->setForeground(QColor(App::ColorOther)); itemStatus->setForeground(QColor(App::ColorOther)); itemStatus->setText("失效"); } } void DeviceHelper::setColor(QTableWidgetItem *itemValue, QTableWidgetItem *itemStatus, float value, float max, float min, const QString &alarmType) { //这里还有个未处理的,是否须要对初始值进行判断报警 if (value == 0) { itemValue->setForeground(QColor(App::ColorZero)); itemStatus->setForeground(QColor(App::ColorZero)); } else if (value > max) { itemValue->setForeground(QColor(App::ColorUpper)); itemStatus->setForeground(QColor(App::ColorUpper)); } else if (value < min) { itemValue->setForeground(QColor(App::ColorLimit)); itemStatus->setForeground(QColor(App::ColorLimit)); } else { itemValue->setForeground(QColor(App::ColorNormal)); itemStatus->setForeground(QColor(App::ColorNormal)); } itemValue->setText(QString::number(value)); }