Qt编写数据可视化大屏界面电子看板12-数据库采集
liebian365 2024-10-17 14:01 29 浏览 0 评论
一、前言
数据采集是整个数据可视化大屏界面电子看板系统核心功能,没有数据源,这仅仅是个玩具UI,没啥用,当然默认做了定时器模拟数据,产生随机数据,这个可以直接配置文件修改来选择采用何种数据采集方法,总结了一下基本上会有这样几种数据源,timer-模拟数据 db-数据库采集 tcp-网络采集 http-post请求,大量的web会选择采用http作为post网络请求来获取数据,而对于本人来说,更喜欢用数据库作为数据源,这样可以避免很多扯皮的事情,比如请求出错或者得到错误的数据等,而数据库是死的,不涉及到其他任何程序的干扰,也不需要做任何对接,只要规范好数据库表和字段即可。
本系统默认采用mysql数据库,当然也支持其他数据,甚至包括了sqlite这种小众的数据库,Qt对数据库的封装也是非常完美的,反正在我使用的这些年过程中,没有发现过什么BUG或者事故,Qt提供了一个统一的数据库接口,这对于程序员来说是巨大的福音,比如查询数据库,QSqlQuery查询的结果,统一用query.value(i)或者,这个数据是通用类型,可以转换成你想要的数据类型,这样就拓展性和兼容性非常强大了。
在本系统中,各个模块的采集间隔都可以自由定义,默认5秒钟采集一次,我采用的办法是,开启一个线程,在线程中打开数据,然后提供方法插入要执行的sql语句,插入的同时记得给定标识符,以便返回结果的时候标识,这样就形成了一个万能的方法,自动排队,也不会说冲突之类的,一个类管理所有的数据库采集,文字末尾会贴出完整代码。
二、电子看板介绍
电子看板是目视化管理的一种表现形式,即对数据的状况一目了然地表现,主要是对于管理项目,它通过利用形象直观而又色彩适宜的各种视觉感知信息来组织现场生产活动,目视管理依据人类的生理特征,在生产现场充分利用信号灯、标识牌、符号颜色等方式来发出视觉信号,鲜明准确地刺激人的神经末梢,快速地传递信息,形象直观地将潜在的问题和浪费现象都显现出来。以便任何人都可以及时掌握管理现状和必要的情报,从而能够快速制定并实施应对措施。因此,管理看板是发现问题、解决问题的非常有效且直观的手段,是优秀的现场管理必不可少的工具之一。
三、功能特点
1. 整体总共分三级界面,一级界面是整体布局,二级界面是单个功能模块,三级界面是单个控件。
2. 子控件包括饼图+圆环图+曲线图+柱状图+柱状分组图+横向柱状图+横向柱状分组图+合格率控件+百分比控件+进度控件+设备状态面板+表格数据+地图控件(包括动态闪烁点+迁徙图等)+视频控件+其他控件等。
3. 二级界面可以自由拖动悬浮,支持最小化最大化关闭,响应双击自定义标题栏。
4. 数据源支持数据库采集(默认)、网络通信、网络请求等,可自由设定每个子界面的采集间隔即数据刷新频率。
5. 采用纯QWidget编写,支持Qt4.6到Qt5.12.3任何版本,支持嵌入式linux比如树莓派、香橙派、全志、imx6等。
6. 提供三个内核版本,自定义控件版本+qchart版本+echart版本。
7. 内置多套配色风格样式,默认紫色,支持任何分辨率。
8. 可设置标题+目标分辨率+布局方案,启动立即应用。
9. 可设置主背景颜色+面板颜色+十字线游标颜色。
10. 可设置多条曲线颜色,没有设置颜色的情况下内置15套精美颜色随机应用。
11. 可设置标题栏背景颜色+文字颜色。
12. 可设置曲线图表背景颜色+文字颜色+网格颜色。
13. 可设置正常颜色+警戒颜色+报警颜色+禁用颜色+百分比进度颜色。
14. 可分别设置各种字体大小,比如全局+软件名称+标题栏+子标题栏+加粗标签等。
15. 可设置标题栏高度+表头高度+行高度。
16. 曲线支持游标+悬停高亮数据点和显示值,柱状图支持顶部(可设置顶端+上部+中间+底部)显示数据,全部自适应计算位置。
17. 主界面直接鼠标右键切换布局+配色方案+关闭开启某个二级窗体。
18. 自动记忆所有子窗口的大小和位置,下次启动立即应用。
19. 动态加载布局方案菜单,可以动态新建布局、恢复布局、保存布局、另存布局等,用户可以制造任意布局。
20. 二级窗体,双击从主窗体分离出来浮动,可以自由调整大小。再次双击标题栏最大化,再次双击还原。
21. 每个模块都可以自定义采集速度,如果是数据库采集会自动排队处理。
五、特别说明
1. 可执行文件同级文件夹有layout+layout_1440+layout_1920,程序默认自动识别分辨率并加载对应的布局文件夹,比如1920分辨率则从layout_1920文件夹加载布局,并作为整体布局文件夹。
2. 程序默认是模拟数据,如果需要从数据库采集则修改配置文件WorkMode=db即可。
3. 如果发现布局拖动乱了,可以直接鼠标右键选择恢复布局即可,在保存布局以前。
4. 在中间地图模块鼠标右键可以弹出菜单,切换布局和配色方案等。
5. 在模块的标题栏上右键可以弹出默认的dock菜单,用来显示和隐藏各模块。
6. 软件关闭过程中会自动保存布局,下次启动以后自动应用。
7. 如果使用的默认的默认的配色方案比如紫色风格,则配置文件中的颜色全部无效,会自动应用代码中的颜色,如果需要启用自定义的颜色,则将配置文件的 Theme=\x81ea\x5b9a\x4e49\x98ce\x683c 即可。此时打开软件会应用配置文件中的颜色。
8. 右键菜单可以截图保存,默认命名为 配色方案名称_布局方案名称.png 保存在snap目录下。
9. 如果是XP系统请先执行fixff.cmd,用来修复ffmpeg在XP上不可用的BUG。
10. 在二级窗体的标题栏上右键弹出模块菜单,可以对单个模块打开关闭,其他地方右键全局菜单。
11. 会不定期更新程序,欢迎各位提出批评和建议。
六、效果图
七、核心代码
#include "datadb.h" #include "quiwidget.h" QScopedPointer<DataDb> DataDb::self; DataDb *DataDb::Instance() { if (self.isNull()) { static QMutex mutex; QMutexLocker locker(&mutex); if (self.isNull()) { self.reset(new DataDb); } } return self.data(); } DataDb::DataDb(QObject *parent) : QThread(parent) { stopped = false; dbOkLocal = false; errorCount = 0; lastCheckTimeLocal = QDateTime::currentDateTime(); checkConn = false; checkInterval = 30; dbTypeLocal = DbType_MySql; connNameLocal = "qt_sql_default_connection"; hostNameLocal = "127.0.0.1"; portLocal = 3306; dbNameLocal = "db_mysql"; userNameLocal = "root"; userPwdLocal = "root"; connect(this, SIGNAL(error(QString)), this, SLOT(doError(QString))); } DataDb::~DataDb() { this->stop(); this->wait(); } void DataDb::run() { //打开数据库 openDb(); msleep(1000); while(!stopped) { //定时执行一次校验数据库连接是否正常 QDateTime now = QDateTime::currentDateTime(); if (checkConn && lastCheckTimeLocal.secsTo(now) >= checkInterval) { checkDb(); lastCheckTimeLocal = now; continue; } //如果数据库连接正常则处理数据,不正常则重连数据库 if (!dbOkLocal) { if (errorCount >= 3) { closeDb(); msleep(3000); openDb(); emit debug(QString("重连本地数据库%1").arg(dbOkLocal ? "成功" : "失败")); msleep(3000); } } else { //取出队列sql语句执行 if (tags.count() > 0) { //从最前面开始取 QMutexLocker locker(&mutex); QString tag = tags.takeFirst(); QString sql = sqls.takeFirst(); //qDebug() << TIMEMS << tag << sql; QSqlQuery query(dbConnLocal); if (query.exec(sql)) { QStringList data; while(query.next()) { int count = query.record().count(); for (int i = 0; i < count; i++) { data << query.value(i).toString(); } } emit receiveData(tag, data); } } msleep(10); } } stopped = false; } void DataDb::doError(const QString &msg) { QUIHelper::showMessageBoxError(msg, 3); } bool DataDb::openDb() { //可以自行增加其他数据库的支持 if (dbTypeLocal == DbType_Sqlite) { dbConnLocal = QSqlDatabase::addDatabase("QSQLITE", connNameLocal); dbConnLocal.setDatabaseName(dbNameLocal); } else if (dbTypeLocal == DbType_MySql) { dbConnLocal = QSqlDatabase::addDatabase("QMYSQL", connNameLocal); dbConnLocal.setConnectOptions("MYSQL_OPT_RECONNECT=1;MYSQL_OPT_CONNECT_TIMEOUT=1;MYSQL_OPT_READ_TIMEOUT=1;MYSQL_OPT_WRITE_TIMEOUT=1"); dbConnLocal.setHostName(hostNameLocal); dbConnLocal.setPort(portLocal); dbConnLocal.setDatabaseName(dbNameLocal); dbConnLocal.setUserName(userNameLocal); dbConnLocal.setPassword(userPwdLocal); } errorCount = 0; dbOkLocal = dbConnLocal.open(); if (!dbOkLocal) { emit error("打开数据库失败!请检查用户名和密码是否正确!"); } return dbOkLocal; } bool DataDb::checkDb() { QDateTime dtStart = QDateTime::currentDateTime(); QString sql = "select 1"; QSqlQuery query(dbConnLocal); dbOkLocal = query.exec(sql); dbOkLocal ? (errorCount = 0) : errorCount++; QDateTime dtEnd = QDateTime::currentDateTime(); double ms = dtStart.msecsTo(dtEnd); emit debug(QString("检查本地数据库连接(共 %1 条/用时 %2 秒)").arg(1).arg(QString::number(ms / 1000, 'f', 3))); return dbOkLocal; } void DataDb::closeDb() { dbConnLocal.close(); QSqlDatabase::removeDatabase(connNameLocal); dbOkLocal = false; emit debug("关闭本地数据库"); } void DataDb::stop() { stopped = true; } void DataDb::setConnInfo(DataDb::DbType dbType, const QString &connName, const QString &hostName, int port, const QString &dbName, const QString &userName, const QString &userPwd) { this->dbTypeLocal = dbType; this->connNameLocal = connName; this->hostNameLocal = hostName; this->portLocal = port; this->dbNameLocal = dbName; this->userNameLocal = userName; this->userPwdLocal = userPwd; } void DataDb::setCheckConn(bool checkConn) { this->checkConn = checkConn; } void DataDb::setCheckInterval(int checkInterval) { if (checkInterval > 5 && this->checkInterval != checkInterval) { this->checkInterval = checkInterval; } } QSqlDatabase DataDb::getDb() { return dbConnLocal; } bool DataDb::getOk() { return dbOkLocal; } void DataDb::select(const QString &tableName, const QString &columnName, bool append) { //超过队列中最大数量限制则无需处理 QMutexLocker locker(&mutex); if (tags.count() < 100) { //如果是append表示追加在队列末尾,否则插到最前面优先级最高 if (append) { tags << tableName; sqls << QString("select %1 from %2").arg(columnName).arg(tableName); } else { tags.insert(0, tableName); sqls.insert(0, QString("select %1 from %2").arg(columnName).arg(tableName)); } } }
相关推荐
- 深度解密epoll 如何工作的?(epoll基本处理流程)
-
epoll...
- 大乐透第19082期:头奖开出7注1000万分落六地 奖池41亿元
-
2019年7月17日晚开奖的体彩超级大乐透第19082期开奖号码为:前区06、18、20、21、31,后区03、04。本期大乐透前区号码五区比为1:0:3:0:1,二区和四区号码没有给出。当期前区和值...
- 【开奖】4月27日周六:福彩、体彩(2021年4月27日体彩开奖结果)
-
4月27日开奖福彩3D第2019110期:61222选5第2019110期:0812202122排列3第19110期:303排列5第19110期:30305大乐透第19047期:0304...
- “红狒狒”落户哈尔滨铁路局(哈尔滨铁路红肠)
-
这几天,“红人”“红狒狒”在牡丹江机务段可引起了不小的轰动,众粉丝争相与其拍照留念,在该段人气爆棚!“红狒狒”到底何许人也?“红狒狒”,中文名:和谐3D型电力机车;绰号:红狒狒、番茄;制造商:大连机...
- 2D、3D、2.5D,做游戏还是搞噱头?玩家都晕了
-
前言游戏类型就像某种潮流,一种流行罢,另一种接棒成为主流。前两年的新作大多以“开放世界”为标签,在追求纯沙盒的过程中打造出一些细致的分类,比如说“类GTA沙盒”。诚然,纯碎的沙盒游戏并不多见,业内只有...
- 《战神4》PC版宣传片发布 GTX 1070即可60帧畅玩
-
在今年10月的时候索尼PlayStation官方正式宣布圣莫尼卡2018年的《战神4》将于2022年1月14日推出PC版本,官方在今天公布了一段PC版宣传片,并且公开了游戏的配置需求。下面让我们一起来...
- 男星深情好丈夫形象崩塌,半夜搂美女坐大腿,举止亲密
-
近日,于晓光被拍到深夜在酒吧玩,结束后与一名女子一起上车离开。上车后,女子直接坐在了他腿上,他也顺势搂着美女,美女满脸笑容地坐在他腿上玩手机离开。可能有人会好奇,于晓光是谁呢?于晓光是韩国艺人秋瓷炫的...
- d3d12dll丢失怎么修复?d3d12dll加载失败怎么解决?
-
d3d12.dll丢失怎么修复?d3d12.dll加载失败怎么解决?很多朋友想要运行游戏的时候都会遇到这个问题,这种情况该怎么办呢?今天系统之家小编给朋友们讲讲具体的解决方法,操作其实还蛮简单的。...
- 许多玩家反馈《生化4RE》PC一直崩溃 无法进入游戏
-
今日(3月24日),卡普空《生化危机4:重制版》正式发售,然而有部分PC玩家遇到了游戏崩溃等问题。很多玩家在贴吧发帖称游戏遇到了严重的崩溃问题,且经常反复,报错代码普遍为FatalD3Derror...
- 微软正式推出适用于WSL Linux的D3D12 GPU视频加速技术
-
今天,微软正式向WindowsSubsystemforLinux(WSL)用户发布了Direct3D12GPU视频加速支持。在微软通过WSL允许在Linux下使用Open...
- 《怪物猎人:崛起》曙光系统报错“Fatal d3d error”的解决办法
-
《怪物猎人:崛起》曙光系统报错“Fatald3derror”的解决办法不少小伙伴反应《怪物猎人:崛起》DLC曙光预载以后打不开游戏,出现了Fatald3derror类似的错误代码,这类问题的解...
- Mac+双屏,前端程序员的专业配置 - Loctek 乐歌 D3D 双屏电脑显示器支架
-
做FE也有一段日子了,电脑屏幕每天在设计稿、浏览器、IDE、即时通讯工具、Terminal、邮箱之间切换。虽然mac的工作区带来了很多灵活,但是依然略显不足。于是入手支架,把公司配的电脑和显示器发挥起...
- RPC 的原理和简单使用(rpc详解)
-
RPC的概念RPC,RemoteProcedureCall,翻译成中文就是远程过程调用,是一种进程间通信方式。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数。在调用的...
- 大厂开源的golang微服务rpc框架 — kitex
-
提前rpc估计所有的开发同学都知道,不知道的也无所谓,毕竟我也好几年没用了,今天带大家在复习一下。RPC(RemoteProcedureCall):远程过程调用,...
- 干货!一文掌握Protobuf所有语言所有用法,快收藏
-
说实话,Protobuf这个库,让人相见时难别亦难,东风无力百花残,每次等到要用它的时候,总感觉还没有完全掌握它的用法,而实际上等去百度或者谷歌的时候,教程都是多么的凌乱不堪。学会它,最直接关系到的,...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)