Qt编写数据可视化大屏界面电子看板12-数据库采集
一、前言
数据采集是整个数据可视化大屏界面电子看板系统核心功能,没有数据源,这仅仅是个玩具UI,没啥用,当然默认做了定时器模拟数据,产生随机数据,这个可以直接配置文件修改来选择采用何种数据采集方法,总结了一下基本上会有这样几种数据源,timer-模拟数据 db-数据库采集 tcp-网络采集 http-post请求,大量的web会选择采用http作为post网络请求来获取数据,而对于本人来说,更喜欢用数据库作为数据源,这样可以避免很多扯皮的事情,比如请求出错或者得到错误的数据等,而数据库是死的,不涉及到其他任何程序的干扰,也不需要做任何对接,只要规范好数据库表和字段即可。
本系统默认采用mysql数据库,当然也支持其他数据,甚至包括了sqlite这种小众的数据库,Qt对数据库的封装也是非常完美的,反正在我使用的这些年过程中,没有发现过什么BUG或者事故,Qt提供了一个统一的数据库接口,这对于程序员来说是巨大的福音,比如查询数据库,QSqlQuery查询的结果,统一用query.value(i)或者,这个数据是通用类型,可以转换成你想要的数据类型,这样就拓展性和兼容性非常强大了。
在本系统中,各个模块的采集间隔都可以自由定义,默认5秒钟采集一次,我采用的办法是,开启一个线程,在线程中打开数据,然后提供方法插入要执行的sql语句,插入的同时记得给定标识符,以便返回结果的时候标识,这样就形成了一个万能的方法,自动排队,也不会说冲突之类的,一个类管理所有的数据库采集,文字末尾会贴出完整代码。
二、电子看板介绍
电子看板是目视化管理的一种表现形式,即对数据的状况一目了然地表现,主要是对于管理项目,它通过利用形象直观而又色彩适宜的各种视觉感知信息来组织现场生产活动,目视管理依据人类的生理特征,在生产现场充分利用信号灯、标识牌、符号颜色等方式来发出视觉信号,鲜明准确地刺激人的神经末梢,快速地传递信息,形象直观地将潜在的问题和浪费现象都显现出来。以便任何人都可以及时掌握管理现状和必要的情报,从而能够快速制定并实施应对措施。因此,管理看板是发现问题、解决问题的非常有效且直观的手段,是优秀的现场管理必不可少的工具之一。
三、功能特点
- 整体总共分三级界面,一级界面是整体布局,二级界面是单个功能模块,三级界面是单个控件。
- 子控件包括饼图+圆环图+曲线图+柱状图+柱状分组图+横向柱状图+横向柱状分组图+合格率控件+百分比控件+进度控件+设备状态面板+表格数据+地图控件(包括动态闪烁点+迁徙图等)+视频控件+其他控件等。
- 二级界面可以自由拖动悬浮,支持最小化最大化关闭,响应双击自定义标题栏。
- 数据源支持数据库采集(默认)、网络通信、网络请求等,可自由设定每个子界面的采集间隔即数据刷新频率。
- 采用纯QWidget编写,支持Qt4.6到Qt5.12.3任何版本,支持嵌入式linux比如树莓派、香橙派、全志、imx6等。
- 提供三个内核版本,自定义控件版本+qchart版本+echart版本。
- 内置多套配色风格样式,默认紫色,支持任何分辨率。
- 可设置标题+目标分辨率+布局方案,启动立即应用。
- 可设置主背景颜色+面板颜色+十字线游标颜色。
- 可设置多条曲线颜色,没有设置颜色的情况下内置15套精美颜色随机应用。
- 可设置标题栏背景颜色+文字颜色。
- 可设置曲线图表背景颜色+文字颜色+网格颜色。
- 可设置正常颜色+警戒颜色+报警颜色+禁用颜色+百分比进度颜色。
- 可分别设置各种字体大小,比如全局+软件名称+标题栏+子标题栏+加粗标签等。
- 可设置标题栏高度+表头高度+行高度。
- 曲线支持游标+悬停高亮数据点和显示值,柱状图支持顶部(可设置顶端+上部+中间+底部)显示数据,全部自适应计算位置。
- 主界面直接鼠标右键切换布局+配色方案+关闭开启某个二级窗体。
- 自动记忆所有子窗口的大小和位置,下次启动立即应用。
- 动态加载布局方案菜单,可以动态新建布局、恢复布局、保存布局、另存布局等,用户可以制造任意布局。
- 二级窗体,双击从主窗体分离出来浮动,可以自由调整大小。再次双击标题栏最大化,再次双击还原。
- 每个模块都可以自定义采集速度,如果是数据库采集会自动排队处理。
四、配置文件说明
(1)、基本配置参数
字段 | 描述 | 默认值 |
---|---|---|
WorkMode | 工作模式 timer-模拟数据 db-数据库采集 tcp-网络采集 http-post请求 | db |
MapStyle | 中间地图样式 image-静态图片 point-闪烁点 move-迁徙图 | point |
Title | 软件标题,显示在软件中间顶部 | 数字化工厂信息中心 |
Ratio | 分辨率,目前无意义 | 4096*216 |
Layout | 布局方案,每次切换布局方案以后都会保存 | 完整布局 |
Theme | 配色方案,每次切换配色方案以后都会保存 | 紫色风格 |
VideoAddr | 视频流地址,视频模块播放的视频地址 | 凤凰卫视 |
AutoRun | 是否开机启动 | false |
MoveEnable | 模块是否可以拖动,启用以后模块可以任意拖动 | true |
CutLeftBottom | 底部布局左侧是否切掉 | true |
CutRightBottom | 底部布局右侧是否切掉 | true |
StaticLine | 是否绘制静态定位线,为假则绘制游标十字线 | true |
ShowPercent | Y轴是否显示百分比 | true |
StepY | Y轴大尺度步长 | 6 |
CursorHideTime | 用户不操作鼠标自动隐藏鼠标的时间间隔,单位秒 | 5 |
(2)、颜色配置参数
字段 | 描述 | 默认值 |
---|---|---|
ColorMainBg | 主背景颜色 | QColor(4, 7, 38) |
ColorPanelBg | 面板背景颜色 | QColor(26, 29, 60) |
ColorLine | 十字线定位线颜色 | QColor(255, 0, 0) |
ColorLine1 | 线条1颜色 | QColor(0, 176, 180) |
ColorLine2 | 线条2颜色 | QColor(32, 159, 223) |
ColorLine3 | 线条3颜色 | QColor(255, 192, 0) |
ColorTitleBg | 标题栏背景颜色 | QColor(48, 48, 85) |
ColorTitleText | 标题栏文字颜色 | QColor(255, 255, 255) |
ColorChartBg | 曲线图表背景颜色 | QColor(38, 41, 74) |
ColorChartText | 曲线图表文字颜色 | QColor(250, 250, 250) |
ColorChartGrid | 曲线图表网格颜色 | QColor(180, 180, 180) |
ColorOk | 正常颜色 | QColor(0, 176, 180) |
ColorLow | 警戒颜色 | QColor(255, 192, 0) |
ColorAlarm | 报警颜色 | QColor(214, 77, 84) |
ColorDisable | 禁用背景颜色 | QColor(210, 210, 210) |
ColorPercent | 环形百分比背景颜色 | QColor(0, 254, 254) |
(3)、字体和尺寸配置参数
字段 | 描述 | 默认值 |
---|---|---|
MainFont | 全局字号 | 微软雅黑,12 |
NameFont | 软件名称字号 | 19 |
LabFont | 加粗标签字号 | 12 |
DeviceFont | 设备面板字号 | 12 |
SubTitleFont | 模块子标题栏字号 | 13 |
TitleFont | 模块标题栏字号 | 15 |
TitleHeight | 模块标题栏高度 | 23 |
HeadHeight | 表格表头高度 | 28 |
RowHeight | 表格行高度 | 25 |
(4)、采集速度配置参数
字段 | 描述 | 默认值 |
---|---|---|
IntervalModule1 | 模块1采集间隔 | 5000 |
IntervalModule2 | 模块2采集间隔 | 5000 |
IntervalModule3 | 模块3采集间隔 | 5000 |
IntervalModule4 | 模块4采集间隔 | 5000 |
IntervalModule5 | 模块5采集间隔 | 5000 |
IntervalModule6 | 模块6采集间隔 | 5000 |
IntervalModule7 | 模块7采集间隔 | 5000 |
IntervalModule8 | 模块8采集间隔 | 5000 |
(5)、本地数据库配置参数
字段 | 描述 | 默认值 |
---|---|---|
LocalDBType | 本地数据库类型,Sqlite、Mysql等 | Mysql |
LocalDBIP | 本地数据库主机地址 | 127.0.0.1 |
LocalDBPort | 本地数据库端口 | 3306 |
LocalDBName | 本地数据库名称 | bigscreen |
LocalUserName | 本地数据库用户名 | root |
LocalUserPwd | 本地数据库密码 | root |
五、特别说明
- 可执行文件同级文件夹有layout+layout_1440+layout_1920,程序默认自动识别分辨率并加载对应的布局文件夹,比如1920分辨率则从layout_1920文件夹加载布局,并作为整体布局文件夹。
- 程序默认是模拟数据,如果需要从数据库采集则修改配置文件WorkMode=db即可。
- 如果发现布局拖动乱了,可以直接鼠标右键选择恢复布局即可,在保存布局以前。
- 在中间地图模块鼠标右键可以弹出菜单,切换布局和配色方案等。
- 在模块的标题栏上右键可以弹出默认的dock菜单,用来显示和隐藏各模块。
- 软件关闭过程中会自动保存布局,下次启动以后自动应用。
- 如果使用的默认的默认的配色方案比如紫色风格,则配置文件中的颜色全部无效,会自动应用代码中的颜色,如果需要启用自定义的颜色,则将配置文件的 Theme=\x81ea\x5b9a\x4e49\x98ce\x683c 即可。此时打开软件会应用配置文件中的颜色。
- 右键菜单可以截图保存,默认命名为 配色方案名称_布局方案名称.png 保存在snap目录下。
- 如果是XP系统请先执行fixff.cmd,用来修复ffmpeg在XP上不可用的BUG。
- 在二级窗体的标题栏上右键弹出模块菜单,可以对单个模块打开关闭,其他地方右键全局菜单。
- 可执行文件下载地址:https://pan.baidu.com/s/1o97IGvZgTgDhlkuXQa4B0w 提取码:r2bv。
- 会不定期更新程序,欢迎各位提出批评和建议。
六、效果图
七、核心代码
#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));
}
}
}
Qt编写数据可视化大屏界面电子看板12-数据库采集的更多相关文章
- Qt编写数据可视化大屏界面电子看板系统
一.前言 目前大屏大数据可视化UI这块非常火,趁热也用Qt来实现一个,Qt这个一站式超大型GUI超市,没有什么他做不了的,大屏电子看板当然也不在话下,有了QSS和QPainter这两个无敌的工具组合, ...
- Qt编写数据可视化大屏界面电子看板9-曲线效果
一.前言 为了编写数据可视化大屏界面电子看板系统,为了能够兼容Qt4和嵌入式linux系统,尤其是那种主频很低的,但是老板又需要在这种硬件上(比如树莓派.香橙派.全志H3.imx6)展示这么华丽的界面 ...
- Qt编写数据可视化大屏界面电子看板11-自定义控件
一.前言 说到自定义控件,我是感觉特别熟悉的几个字,本人亲自原创的自定义控件超过110个,都是来自各个行业的具体应用真实需求,而不是凭空捏造的,当然有几个小控件也有点凑数的嫌疑,在编写整个数据可视化大 ...
- Qt编写数据可视化大屏界面电子看板8-调整间距
一.前言 在数据可视化大屏界面电子看板系统中,前期为了使用目标客户机,调整间距是必不可少的工作,QMainWindow中的QDockWidget,会默认生成布局和QSplitter调整宽高大小,鼠标移 ...
- Qt编写数据可视化大屏界面电子看板4-布局另存
一.前言 布局另存是数据可视化大屏界面电子看板系统中的额外功能之一,主要用于有时候用户需要在现有布局上做个微调,然后直接将该布局另存为一个布局配置文件使用,可以省略重新新建布局重新来一次大的调整的工作 ...
- Qt编写数据可视化大屏界面电子看板3-新建布局
一.前言 能够新建布局,也是数据可视化大屏界面电子看板系统中的必备功能之一,新建布局这样的功能一般做到右键菜单中,单击新建布局菜单,弹出输入框要求输入新的布局的名称,为了更符合国情,直接支持中文名称, ...
- Qt编写数据可视化大屏界面电子看板2-配色方案
一.前言 做完整个数据可视化大屏界面电子看板系统后,为了提升点逼格,需要提供好几套默认的风格样式以供选择,这样用户可以选择自己喜欢的配色方案来作为整个系统的颜色方案,去看了下市面上大部分的大屏电子看板 ...
- Qt编写数据可视化大屏界面电子看板1-布局方案
一.前言 布局方案在整个数据可视化大屏界面电子看板系统中,是除了基础功能以外的核心功能之一,只有具备了布局方案这个功能,才能让用户随意调整自己想要的布局,保存成自定义名称的布局配置文件,这样就大大增加 ...
- Qt编写数据可视化大屏界面电子看板5-恢复布局
一.前言 恢复布局这个功能在整个数据可视化大屏界面电子看板系统中非常有用,很多时候不小心把现有布局拖动乱了,(当然如果不想布局被拖动改动,可以修改配置文件中的MoveEnable参数来控制,默认为真表 ...
随机推荐
- Nginx系列1.1:ubuntu16.04编译nginx-rtmp流媒体服务器
1.下载nginx和nginx-rtmp-module nginx官网:nginx.org tar.gz文件 解压缩命令: wget https://nginx.org/download/nginx- ...
- split()函数实现
#split函数实现: ss='** *axx* *bv** *ctt** **dff***' result=[] def split_1(ss,a,times=len(ss)): i=0 n=0 w ...
- Netty搭建服务端的简单应用
Netty简介 Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客 ...
- 使用python批量造测试数据
# -*- coding:utf-8 -*- import json import os import time class Virtual_Data: def __init__(self): sel ...
- linux基础知识和常用命令
1.修改主机名 切换到root,然后执行 vim /etc/sysconfig/network,进入其中,更改hostname即可.insert进入修改,esc+:,wq保存退出. 2.用户切换 普通 ...
- Catalan Number-卡特兰数入门
卡特兰数 首先,我们设f(n)=序列个数为n的出栈序列种数.同时,我们假定,从开始到栈第一次出到空为止,这段过程中第一个出栈的序数是k.特别地,如果栈直到整个过程结束时才空,则k=n. 令h(0)=1 ...
- word如何选择图片粘贴
自动导入Word图片,或者粘贴Word内容时自动上传所有的图片,并且最终保留Word样式,这应该是Web编辑器里面最基本的一个需求功能了.一般情况下我们将Word内容粘贴到Web编辑器(富文本编辑器) ...
- 5分钟记住列表的使用功能-Python基础前传(7)
学习任何一门技术,最重要的是逻辑而不是内容,仅会内容,我们仅仅是技术的使用者,但如果我们懂得了技术背后的逻辑,我们就是技术的创造者,所以同样领域的工作,有人月入5千,有人月入5万,就是这个差别: 学技 ...
- ubuntu14.04重启网卡的三种方法
Linux重启网卡的三种方法: 一.network 利用root帐户 # service network restart 或者/etc/init.d/networking restart 二.ifdo ...
- shell uniq 统计,计数
uniq选项与参数-i:忽略大小写-c:进行计数[zhang@localhost ~]$ cat 2.txt helloHelloWOrldabcabcABChello1 对2.txt进行sort后, ...