一、前言

用表格来展示采集到的数据,是很多组态系统中最常见的方法,一个表格能够展示的数据特别多,在本系统中,默认做的也是通过表格的形式来展示数据,目前是将所有的设备放在一个表格中,后期可能按照不同控制器对应一个表格,一般来说一个场所对应一个控制器,一个控制器下面会有很多个探测器,相当于终端传感器,最终这些终端传感器采集到的数据,传给控制器,控制器打包上发,软件这边接收到以后根据不同的位解析对应的数据。

表格展示数据,需要对不同状态的数据不同颜色显示,这样一目了然,比如至少区分正常状态、低报状态、高报状态、离线状态这几种,对应的文字颜色正常绿色、低报黄色、高报红色、离线黑色等,当然这些具体颜色可以在系统设置中配置。理想是好的,现实很残忍,就比如这个颜色显示,调用setForeground是可以设置好文字颜色,但是使用过程中你会发现,和全局的样式表冲突了,鼠标移上去之后变成了悬停的颜色了,但是QTableWidgetItem并没有提供悬停颜色、按下颜色的单独设置。

这个时候委托就派上用场了,或者自定义一个QTableWidget拦截重新painter,终极大法建议用自定义委托,更万能更安全,而且更通用,相当于设置一个自定义禁用委托列,设置到对应的列,然后改列悬停也好按下也罢,都是按照默认的文字颜色绘制,并不要用全局样式表中的颜色,这样就完美的避开了冲突的缺陷。很多人其实都遇到了这个问题,明明通过setForeground、setTextColor设置了颜色,结果鼠标移上去就变了,导致看到的效果和实际的效果不一致。

二、功能特点

2.1 软件模块

  1. 设备监控模块,包括数据监控(表格形式展示)、设备面板(面板形式展示)、地图监控(地图形式展示)、曲线监控(曲线形式展示)。
  2. 数据查询模块,包括报警记录、运行记录、操作记录。
  3. 系统设置模块,包括基本设置、端口管理、控制器管理、探测器管理、报警联动、类型设置等。
  4. 其他设置模块,包括用户管理、地图管理、位置调整、组态设计、设备调试等。

2.2 基础功能

  1. 设备数据采集,支持串口、网络,串口可设置串口号、波特率,网络可设置IP地址、通讯端口。
  2. 每个端口支持采集周期时间,默认1秒钟一个设备。
  3. 支持设置通讯超时次数,默认3次。
  4. 支持最大重连时间,用于重新读取离线的设备。
  5. 控制器信息,能够添加控制器名称,选择控制器地址、控制器型号,设置该控制器下面的探测器数量。
  6. 探测器信息,能够添加位号、探测器型号、气体种类、气体符号、高报值、低报值、缓冲值、清零值、是否启用、报警声音、背景地图、存储周期、数值换算小数点位数、报警延时时间、报警的类型(HH,LL,HL)等。
  7. 类型管理可配置控制器型号、探测器型号、气体种类、气体符号等。
  8. 地图支持导入和删除,所有的探测器在地图上的位置可自由拖动保存。
  9. 端口信息、控制器信息、探测器信息、类型信息、用户信息等,都支持导入、导出、导出到excel、打印。
  10. 运行记录、报警记录、操作记录,都支持多条件组合查询,比如时间段、控制器、探测器等,所有记录支持导出到excel/pdf和打印。
  11. 运行记录、报警记录、操作记录都可删除指定时间范围内的数据。
  12. 系统设置可选择对应表最大保存记录数,自动清理早期数据,留出足够的空间存储重要的数据。
  13. 报警短信转发,支持多个接收手机号码,可设定发送间隔,比如即时发送或者6个小时发送一次所有的报警信息,短信内容过长,自动拆分多条短信。
  14. 报警邮件转发,支持多个接收邮箱,可设定发送间隔,比如即时发送或者6个小时发送一次所有的报警信息,支持附件发送。
  15. 设置软件的中文标题、英文标题、logo路径、版权所有等。
  16. 开关设置开机运行、报警声音、自动登录、记住密码等。
  17. 报警声音可设置播放次数,界面风格样式提供18套皮肤文件选择。
  18. 用户管理,包括用户权限配置,不同用户可以有不同模块的权限。
  19. 用户登录和用户退出,可以记住密码和自动登录,超过三次报错提示并关闭程序。
  20. 四种监控模式,设备面板监控、地图监控、表格数据监控、曲线数据监控,可自由切换,四种模式下都实时展示采集到的数据,报警闪烁等。
  21. 报警继电器联动,一个位号可以跨串口联动多个模块和继电器号,支持多对多。

2.3 特色功能

  1. 通信协议支持modbus_com、modbus_tcp_rtu,后期拓展mqtt等协议。
  2. 数据源除了真实的硬件设备采集,还可选数据库采集,这样用户可以安排其他程序员比如java程序员将前端采集好的数据放到数据库,本系统直接从数据库采集即可。数据库采集模式可以作为通用的系统使用,更适合多人多系统协作。
  3. 智能跳过超时的设备,加快对在线设备的采集速度,当设备数量很多的时候尤其有用。
  4. 对智能跳过的超时的设备,在设定的重连时间自动采集一次,以便探测设备是否又重新上线。
  5. 每个探测器可控是否启用,不启用则不会采集,也不会在界面显示,相当于运行阶段临时关闭。
  6. 探测器可设置缓冲值和报警延时时间,在该值附近波动产生的报警,不计入报警,只有持续处于报警值且超过报警延时时间才算真正报警,这样可以规避很多波动导致的误报。
  7. 探测器可设置存储周期,按照设定的时间来存储一条运行记录,可以按照重要程度对重要性高的设定存储周期短一些,不重要的设定大一些,这样可以节省不少的存储空间,也保证了重要的数据及时存储。
  8. 探测器可设置清零值,在一些高精度高灵敏的设备可能出厂的时候默认值未必是0,需要设定清零值来表示初始值。
  9. 探测器可设置小数点,用于计算后的真实数据控制小数点点位显示,相当于除以10、除以100、除以1000,这样大部分的探测器数据直接通过小数点位设置控制真实换算后的值,极个别的需要特殊转换的可以在通信协议中约定。
  10. 探测器报警的类型支持多种,有些设备是高于某个值高报,低于某个值低报,而有些设备是在最小值最大值范围内是高报,低于最小值低报,高于最大值正常。这样可以分情况处理,涵盖各种报警类型。
  11. 原创数据导入、导出、打印机制,跨平台不依赖任何组件,瞬间导出数据。
  12. 导出到excel的记录支持所有excel、wps等表格文件版本,不依赖excel等软件。
  13. 高报颜色、低报颜色、正常颜色、默认值颜色等,都可以自由设置。
  14. 支持云端数据同步,将本地采集到的数据实时同步到云端。
  15. 支持网络转发和网络接收,网络接收开启后,软件从udp接收数据进行解析。网络转发支持多个目标IP,这样就实现了本地采集的软件,自由将数据转到客户端,随时查看采集到的数据。
  16. 自动记住用户最后停留的界面以及其他配置信息,重启后自动应用。
  17. 报警自动切换到对应的地图,探测器按钮闪烁,表格数据对应颜色显示。
  18. 双击探测器图标,弹出对应探测器详细信息,可以根据需要定制回控操作。
  19. 数据库支持多种,包括sqlite、mysql、sqlserver、postgresql、oracle、人大金仓等。
  20. 本地设备采集到的数据实时上传到云端,以便手机APP或者web等其他方式提取。
  21. 自带设备模拟工具,支持不同型号的多个设备数据模拟,同时还带数据库数据模拟,以便在没有设备的时候测试数据。
  22. 标准modbus协议,各种控制器类型、探测器类型、种类、符号等全部自定义,非常灵活和强大,通信协议示例数据非常完整,通用各种modbus协议系统,适用于各种应用场景接入。
  23. 同时集成了串口通信、网络通信、数据库通信、数据导入导出打印、通信协议解析、界面UI、全局换肤等众多组件和知识点,非常适合新手入门和进阶。
  24. 支持xp、win7、win10、、win11、linux、mac、各种国产系统(UOS、中标麒麟、银河麒麟等)、嵌入式linux等系统。
  25. 注释完整,项目结构清晰,超级详细完整的使用开发手册,精确到每个代码文件的功能说明,不断持续迭代版本。

三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人主页:https://blog.csdn.net/feiyangqingyun
  4. 知乎主页:https://www.zhihu.com/people/feiyangqingyun
  5. 产品主页:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  6. 在线文档:https://feiyangqingyun.gitee.io/qwidgetdemo/iotsystem/
  7. 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_iotsystem.zip。
  8. 文章导航:https://qtchina.blog.csdn.net/article/details/121330922

四、效果图

五、相关代码

void frmViewData::initForm()
{
//初始化设备表格数据
DeviceHelper::setTableData(ui->tableWidget);
DeviceHelper::initDeviceData(); //设置自定义委托以便原有的颜色不改变 不然选中行的时候会应用样式的颜色
DbDelegate *d_disable7 = new DbDelegate(this);
d_disable7->setDelegateEnable(false);
d_disable7->setDelegateColumn(7);
ui->tableWidget->setItemDelegateForColumn(7, d_disable7); DbDelegate *d_disable9 = new DbDelegate(this);
d_disable9->setDelegateEnable(false);
d_disable9->setDelegateColumn(9);
ui->tableWidget->setItemDelegateForColumn(9, d_disable9);
} void DeviceHelper::initDeviceData()
{
if (deviceData == NULL) {
return;
} QList<QString> columnNames = AppData::TableDataColumns.split("|");
QList<int> columnWidths;
if (QUIHelper::deskWidth() < 1360) {
columnWidths << 50 << 100 << 110 << 100 << 120 << 90 << 80 << 70 << 70 << 70;
} else if (QUIHelper::deskWidth() < 1440) {
columnWidths << 50 << 110 << 130 << 110 << 140 << 100 << 80 << 70 << 70 << 70;
} else {
columnWidths << 55 << 115 << 140 << 130 << 150 << 120 << 80 << 70 << 70 << 70;
} //设置列数列宽标题文本集合等
int columnCount = columnNames.count();
deviceData->setColumnCount(columnCount);
deviceData->setHorizontalHeaderLabels(columnNames);
for (int i = 0; i < columnCount; ++i) {
deviceData->setColumnWidth(i, columnWidths.at(i));
} //载入数据
deviceData->setRowCount(DbData::NodeInfo_Count);
for (int i = 0; i < DbData::NodeInfo_Count; ++i) {
//过滤没有对应设备的探测器
int index = DbData::DeviceInfo_DeviceName.indexOf(DbData::NodeInfo_DeviceName.at(i));
if (index < 0) {
continue;
} QStringList data;
data << QString::number(i + 1);
data << DbData::NodeInfo_PositionID.at(i);
data << DbData::NodeInfo_DeviceName.at(i);
data << DbData::DeviceInfo_DeviceType.at(index);
data << DbData::NodeInfo_NodeName.at(i);
data << DbData::NodeInfo_NodeType.at(i);
data << DbData::NodeInfo_NodeClass.at(i);
data << QString::number(0);
data << DbData::NodeInfo_NodeSign.at(i);
data << "离线"; //后面这几个值是为了方便判断报警范围
data << QString::number(DbData::NodeInfo_NodeUpper.at(i));
data << QString::number(DbData::NodeInfo_NodeLimit.at(i));
data << DbData::NodeInfo_AlarmType.at(i);
addData(data);
}
} void DeviceHelper::addData(const QStringList &data)
{
if (deviceData == NULL) {
return;
} //需要居中的列索引集合
QList<int> centerColumn;
centerColumn << 0 << 5 << 6 << 7 << 8 << 9; //这里行数还必须是静态变量因为会多次调用
static int row = -1;
row++;
for (int i = 0; i < data.count() - 2; ++i) {
QTableWidgetItem *item = new QTableWidgetItem(data.at(i));
if (centerColumn.contains(i)) {
item->setTextAlignment(Qt::AlignCenter);
} //加粗+不同颜色显示对应的数值和状态
if (i == 7 || i == 9) {
QFont font;
font.setPixelSize(QUIConfig::FontSize + 2);
font.setBold(true);
item->setFont(font);
//最后状态列调用函数设置一次
if (i == 9) {
float value = data.at(i - 2).toFloat();
float max = data.at(i + 1).toFloat();
float min = data.at(i + 2).toFloat();
setColor(deviceData->item(row, 7), item, value, max, min);
}
} deviceData->setItem(row, i, item);
}
} void DeviceHelper::clearData()
{
if (deviceData == NULL) {
return;
} deviceData->clearContents();
}

Qt编写物联网管理平台32-表格数据的更多相关文章

  1. 老男孩Day17作业:后台管理平台编辑表格

    一.作业需求: 后台管理平台 ,编辑表格: 1. 非编辑模式: 可对每行进行选择: 反选: 取消选择 2. 编辑模式: 进入编辑模式时如果行被选中,则被选中的行万变为可编辑状态,未选中的不改变 退出编 ...

  2. 年底奉献-QT编写视频监管平台(开源)

    忙忙碌碌又是一年,算算自己毕业四年半,一直在现在这家公司做研发外加总经理助理,研发起初用的VB.NET,而后全面转为C#,最后又全面转为QT,都是由于项目需要,算下来自己搞QT编程也已经四年了,201 ...

  3. vue2.0+elementUI构建单页面后台管理平台

    git:https://github.com/reg21st/vue2-management-platform 访问:https://reg21st.github.io/vue2-management ...

  4. PowerDotNet平台化软件架构设计与实现系列(12):HCRM人员管理平台

    技术服务于业务,良好的技术设计和实现能够大幅提升业务质量和效率. PowerDotNet已经形成了自己的开发风格,很多项目已被应用于生产环境,可行性可用性可靠性都得到了生产环境验证. 编程是非常讲究动 ...

  5. Qt编写数据可视化大屏界面电子看板系统

    一.前言 目前大屏大数据可视化UI这块非常火,趁热也用Qt来实现一个,Qt这个一站式超大型GUI超市,没有什么他做不了的,大屏电子看板当然也不在话下,有了QSS和QPainter这两个无敌的工具组合, ...

  6. Qt编写数据可视化大屏界面电子看板12-数据库采集

    一.前言 数据采集是整个数据可视化大屏界面电子看板系统核心功能,没有数据源,这仅仅是个玩具UI,没啥用,当然默认做了定时器模拟数据,产生随机数据,这个可以直接配置文件修改来选择采用何种数据采集方法,总 ...

  7. Qt编写数据可视化大屏界面电子看板11-自定义控件

    一.前言 说到自定义控件,我是感觉特别熟悉的几个字,本人亲自原创的自定义控件超过110个,都是来自各个行业的具体应用真实需求,而不是凭空捏造的,当然有几个小控件也有点凑数的嫌疑,在编写整个数据可视化大 ...

  8. Qt编写数据可视化大屏界面电子看板8-调整间距

    一.前言 在数据可视化大屏界面电子看板系统中,前期为了使用目标客户机,调整间距是必不可少的工作,QMainWindow中的QDockWidget,会默认生成布局和QSplitter调整宽高大小,鼠标移 ...

  9. Qt编写数据可视化大屏界面电子看板7-窗体浮动

    一.前言 窗体浮动的场景也比较多,用途也比较大,比如视频监控模块,有时候需要调整大小和位置,而不是作为dock嵌入到布局中,一旦嵌入到布局中,大小和位置都被布局接管了,只能任由布局使唤,按在地上摩擦的 ...

  10. Qt编写数据可视化大屏界面电子看板6-窗体打开关闭

    一.前言 二级窗体的打开与关闭,这个功能也很有必要,由于整个系统中各种模块数量窗体数量比较多,后期可能还会增加更多,在4K屏幕上可以显示很多的模块,但是有时候有些模块不想显示出来,就需要将该模块关闭掉 ...

随机推荐

  1. 011 Python 的打印(花式变色打印)和注释(为什么加个#号就能注释)

    #!/usr/bin/env python # -*- coding:utf-8 -*- # Datatime:2022/7/18 21:29 # Filename:011 Python 的打印和注释 ...

  2. 云原生爱好者周刊:寻找 Netlify 开源替代品

    开源项目推荐 Coolify Coolify 是一个开源自托管的 Heroku/Netlify 替代品,颜值还不错. Podman Desktop Podman Desktop 是针对 Podman ...

  3. 深度学习入门笔记——Transform的使用

    Transfrom是什么? 可以看作是一个图像处理的工具箱,通过查看Transform类可以找到不同的图像处理方法 更准确的说,Transform中有各种类的的定义,我们可以通过继承或者构造这些类,然 ...

  4. typescript 编译报错 不能用于索引类型

    Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 't ...

  5. Nuxt.js 应用中的 nitro:build:before 事件钩子详解

    title: Nuxt.js 应用中的 nitro:build:before 事件钩子详解 date: 2024/11/4 updated: 2024/11/4 author: cmdragon ex ...

  6. Mysql篇-Buffer Pool中的三大链表

    为什么要有 Buffer Pool? 虽然说 MySQL 的数据是存储在磁盘里的,但是也不能每次都从磁盘里面读取数据,这样性能是极差的. 要想提升查询性能,那就加个缓存.所以,当数据从磁盘中取出后,缓 ...

  7. jenkins拉取github代码报错问题解决

    问题起因: 踩坑踩坑 用jenkins拉取github项目的代码时,配置完成点击构建时,报错信息为:Couldn't find any revision to build. Verify the re ...

  8. 内网渗透之不出网上线CobaltStrike技巧

    目录 前言 smb beacon上线 tcp listener转发上线 http代理上线 tcp beacon正向连接上线 题外话 - cs和msf的权限传递 cs派生给msf msf派生给cs 前言 ...

  9. 【昌哥IT课堂】MySQL8.3 EXPLAIN中的新JSON格式(译)

    MySQL提供了两个用于分析查询计划的强大工具:EXPLAIN和EXPLAIN ANALYZE.EXPLAIN显示优化器选择的执行计划,并在执行之前停止,而EXPLAIN ANALYZE实际执行查询并 ...

  10. PHP之JWT的token登录认证

    1.JWT简介 JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的.自包含的方式,用于作为JSON对象在各方之间安全地传输信息.该信息可以被验证和信任,因为 ...