C/C++ Qt 数据库与Chart历史数据展示
在前面的博文中具体介绍了QChart组件是如何绘制各种通用的二维图形的,本章内容将继续延申一个新的知识点,通过数据库存储某一段时间节点数据的走向,当用户通过编辑框提交查询记录时,程序自动过滤出该时间节点下所有的数据,并将该数据动态绘制到图形组件内,实现动态查询图形的功能。
首先通过如下代码,创建Times表,表内记录有某个主机某个时间节点下的数值:
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <iostream>
#include <QStringList>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QDateTime>
#include <QTime>
// 初始化数据库
// https://www.cnblogs.com/lyshark
void InitSql()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("lyshark.db");
if (!db.open())
{
std::cout << db.lastError().text().toStdString()<< std::endl;
return;
}
// 执行SQL创建表
db.exec("DROP TABLE Times");
db.exec("CREATE TABLE Times ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"address VARCHAR(64) NOT NULL, "
"datetime VARCHAR(128) NOT NULL, "
"value INTEGER NOT NULL"
")"
);
db.commit();
db.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
InitSql();
return a.exec();
}
数据库结构如下:

接着编写一个模拟插入数据的案例,该案例每一秒向数据库内插入一条记录,我们运行一段时间。
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <iostream>
#include <QStringList>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QDateTime>
#include <QTime>
// 延时函数
void Sleep(int msec)
{
QTime dieTime = QTime::currentTime().addMSecs(msec);
while(QTime::currentTime() < dieTime)
QCoreApplication::processEvents(QEventLoop::AllEvents,100);
}
// 生成随机数
int GetRandom()
{
int num = qrand() % 100;
return num;
}
// 插入数据
void InsertSQL()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("lyshark.db");
if (!db.open())
{
std::cout << db.lastError().text().toStdString()<< std::endl;
return;
}
for(int index=0;index <99999;index++)
{
QString address = QString("192.168.1.100");
QDateTime curDateTime = QDateTime::currentDateTime();
QString date_time = curDateTime.toString("yyyy-MM-dd hh:mm:ss");
int value = GetRandom();
QString run_sql = QString("INSERT INTO Times(id,address,datetime,value) VALUES (%1,'%2','%3',%4);")
.arg(index).arg(address).arg(date_time).arg(value);
std::cout << "执行插入语句: " << run_sql.toStdString() << std::endl;
db.exec(run_sql);
db.commit();
Sleep(1000);
}
db.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
InsertSQL();
return a.exec();
}
运行插入程序,统计一段时间 从 2021-12-11 15:34:16 到 2021-12-11 15:40:04 停止,表内记录如下:

如果我们需要查询某一个时间节点下的数据,例如查询2021-12-11 15:35:00 - 2021-12-11 15:37:00的数据可以这样写SQL:
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <iostream>
#include <QStringList>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QDateTime>
#include <QTime>
// 输出数据
// https://www.cnblogs.com/lyshark
void SelectSQL()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("lyshark.db");
if (!db.open())
{
std::cout << db.lastError().text().toStdString()<< std::endl;
return;
}
// 查询数据
QSqlQuery query("SELECT * FROM Times;",db);
QSqlRecord rec = query.record();
// 循环所有记录
while(query.next())
{
// 判断当前记录是否有效
if(query.isValid())
{
int id_value = query.value(rec.indexOf("id")).toInt();
QString address_value = query.value(rec.indexOf("address")).toString();
QString date_time = query.value(rec.indexOf("datetime")).toString();
int this_value = query.value(rec.indexOf("value")).toInt();
if(date_time.toStdString() >= "2021-12-11 15:35:00" && date_time.toStdString() <="2021-12-11 15:37:00")
{
std::cout << "value: " << this_value << std::endl;
}
}
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
SelectSQL();
return a.exec();
}
这样就可以将该区间内所有的数据全部过滤出来了:

将过滤参数与QChart组件结合即可实现动态绘图效果,绘制UI界面如下:

当用户点击查询时,直接从数据库内取出数据,并将其动态更新到Chart组件内即可,实现代码如下:
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <iostream>
#include <QStringList>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QDateTime>
#include <QTime>
// 初始化Chart图表
void MainWindow::InitChart()
{
// 创建图表的各个部件
QChart *chart = new QChart();
// 将Chart添加到ChartView
ui->graphicsView->setChart(chart);
ui->graphicsView->setRenderHint(QPainter::Antialiasing);
// 隐藏图例
chart->legend()->hide();
// 设置图表主题色
ui->graphicsView->chart()->setTheme(QChart::ChartTheme(1));
// 创建曲线序列
QLineSeries *series0 = new QLineSeries();
// 序列添加到图表
chart->addSeries(series0);
// 创建坐标轴
QValueAxis *axisX = new QValueAxis; // X轴
axisX->setRange(1, 100); // 设置坐标轴范围
axisX->setLabelFormat("%d %"); // 设置X轴格式
axisX->setMinorTickCount(5); // 设置X轴刻度
QValueAxis *axisY = new QValueAxis; // Y轴
axisY->setRange(0, 100); // Y轴范围
axisY->setMinorTickCount(4); // s设置Y轴刻度
// 设置X于Y轴数据集
chart->setAxisX(axisX, series0); // 为序列设置坐标轴
chart->setAxisY(axisY, series0);
}
// 为序列生成数据
void MainWindow::SetData()
{
// 获取指针
QLineSeries *series0=(QLineSeries *)ui->graphicsView->chart()->series().at(0);
// 清空图例
series0->clear();
// 链接数据库
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("lyshark.db");
if (!db.open())
{
return;
}
// 查询数据
QSqlQuery query("SELECT * FROM Times;",db);
QSqlRecord rec = query.record();
// 赋予数据
qreal t=0,intv=1;
// 循环所有记录
while(query.next())
{
// 判断当前记录是否有效
// https://www.cnblogs.com/lyshark
if(query.isValid())
{
QString address_value = query.value(rec.indexOf("address")).toString();
QString date_time = query.value(rec.indexOf("datetime")).toString();
int this_value = query.value(rec.indexOf("value")).toInt();
// 获取组件字符串
QString start_user_time = ui->dateTimeEdit_Start->text();
QString end_user_time = ui->dateTimeEdit_End->text();
// 将时间字符串转为秒,并计算差值 (秒为单位)
QDateTime start_timet = QDateTime::fromString(start_user_time, "yyyy-MM-dd hh:mm:ss");
QDateTime end_timet = QDateTime::fromString(end_user_time, "yyyy-MM-dd hh:mm:ss");
uint stime = start_timet.toTime_t();
uint etime = end_timet.toTime_t();
// 只允许查询小于180秒的记录
uint sub_time = etime - stime;
if(sub_time <= 180)
{
// 查询指定区间内的数据
if(date_time.toStdString() >= start_user_time.toStdString() && date_time.toStdString() <= end_user_time.toStdString())
{
// std::cout << "区间内的数据: " << this_value << std::endl;
series0->append(t,this_value);
t+=intv;
}
}
else
{
std::cout << "查询范围超出定义." << std::endl;
return;
}
}
}
}
// 将添加的widget控件件提升为QChartView类
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
ui->setupUi(this);
InitChart();
// 初始化时间组件
QDateTime curDateTime = QDateTime::currentDateTime();
// 设置当前时间
ui->dateTimeEdit_Start->setDateTime(curDateTime);
ui->dateTimeEdit_End->setDateTime(curDateTime);
// 设置时间格式
ui->dateTimeEdit_Start->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
ui->dateTimeEdit_End->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
SetData();
}
C/C++ Qt 数据库与Chart历史数据展示的更多相关文章
- C/C++ Qt 数据库与TreeView组件绑定
在上一篇博文<C/C++ Qt 数据库QSql增删改查组件应用>介绍了Qt中如何使用SQL操作函数,并实现了对数据库的增删改查等基本功能,从本篇开始将实现数据库与View组件的绑定,通过数 ...
- C#-WinForm-ListView-表格式展示数据、如何将数据库中的数据展示到ListView中、如何对选中的项进行修改
在展示数据库中不知道数量的数据时怎么展示最好呢?--表格 ListView - 表格形式展示数据 ListView 常用属性 HeaderStyle - "详细信息"视图中列标头的 ...
- qt数据库多线程问题的解决(QSqlDatabase只能在创建它的线程中使用)
Qt数据库由QSqlDatabase::addDatabase()生成的QSqlDatabase只能在创建它的线程中使用, 在多线程中共用连接或者在另外一个线程中创建query都是不支持的几乎国内没有 ...
- Qt添加驱动——Qt数据库之添加MySQL驱动插件
Qt数据库之添加MySQL驱动插件(1) 现在可用的数据库驱动只有3种,在Qt中,我们需要自己编译其他数据库驱动的代码,让它们以插件的形式来使用.下面我们就以现在比较流行的MySQL数据库为例,说明一 ...
- Qt数据库_资料
1. QT笔记_数据库总结(一)-rojian-ChinaUnix博客.html http://blog.chinaunix.net/uid-28194872-id-3631462.html (里面有 ...
- 将数据库中的内容展示出来并将某些value值转换成汉字
1.将数据库中的内容展示出来 前台代码未做改变,刚开始未显示的原因是因为 data-field 跟数据库不一样data-field 需要跟数据库中的一样才可以 2.将某些value值转换成汉字 在li ...
- Qt数据库 QSqlTableModel实例操作(转)
本文介绍的是Qt数据库 QSqlTableModel实例操作,详细操作请先来看内容.与上篇内容衔接着,不顾本文也有关于上篇内容的链接. Qt数据库 QSqlTableModel实例操作是本文所介绍的内 ...
- C/C++ Qt 数据库与TableView多组件联动
Qt 数据库组件与TableView组件实现联动,以下案例中实现了,当用户点击并选中TableView组件内的某一行时,我们通过该行中的name字段查询并将查询结果关联到ListView组件内,同时将 ...
- 从AdventureWorks学习数据库建模——保留历史数据
在业务需求中,经常需要我们在系统中能够记录历史信息,能够查看到历史变动情况,这时我们可以通过增加开始结束时间字段来记录数据的历史版本.对数据的历史记录主要分为:关系.属性历史,实体历史和变更历史. 关 ...
随机推荐
- 解决tomcat的404问题
遇到的问题 点击startup.bat启动tomcat启动成功,但在网页上输入local:8080却显示Access Error: 404 -- Not Found Cannot locate doc ...
- OAuth 2.0 扩展协议之 PKCE
前言 阅读本文前需要了解 OAuth 2.0 授权协议的相关内容, 可以参考我的上一篇文章 OAuth 2.0 的探险之旅. PKCE 全称是 Proof Key for Code Exchange, ...
- python爬取豆瓣电影第一页数据and使用with open() as读写文件
# _*_ coding : utf-8 _*_ # @Time : 2021/11/2 9:58 # @Author : 秋泊酱 # @File : 获取豆瓣电影第一页 # @Project : 爬 ...
- python实现其它形态学操作
目录: (一) 顶帽(原图像与开操作图像的差值)(二) 黑帽(原图像与闭操作图像的差值)(三) 形态学梯度 (1)基本梯度(膨胀后的图像与腐蚀后的图像差值) (2)内部梯度(原图像减去腐蚀后的图像 ...
- [cf1528F]AmShZ Farm
考虑$a_{i}$是"more-equal"的组合意义,有以下构造-- 有$n$个位置,每一次选择一个位置$a_{i}$,在$a_{i}$之后(包括$a_{i}$)的第一个空位上停 ...
- [bzoj1280]卖猪
首先考虑猪无法流动,那么源点向每一个猪圈连猪圈中猪个数的边,每一个顾客向汇点连所需猪的边,每一个猪圈向能打开它的顾客连inf的边,跑最大流即可. 但考虑猪要流动,有一个十分巧妙地做法,将每一个顾客所有 ...
- FastAPI(六十二)实战开发《在线课程学习系统》需求分析
前言 基础的分享我们已经分享了六十篇,那么我们这次分享开始将用一系列的文章分享实战课程.我们分享的系统是在线学习系统.我们会分成不同的模块进行分享.我们的目的是带着大家去用fastapi去实战一次,开 ...
- Win10更新Win11步骤及体验感
Win11发布也有一段时间了,最近工作闲下来才想起来更新一下试试,更新过程还算顺利,需要改一下电脑的主板设置之后就可以下载官方提供的更新包,记录一下安装过程中遇到的问题以便查看. Win11更新 使用 ...
- SNP 过滤(二)
本文转载于https://www.jianshu.com/p/e6d5dd774c6e SNP位点过滤 SNP过滤有两种情况,一种是仅根据位点质量信息(测序深度,回帖质量等)对SNP进行粗过滤.如果使 ...
- 问题记录:SNP 标记 phasing
GATK4 检测的SNP标记,有些位点会在检测过程中完成 phasing,在后续做基因型填充的时候有坑. GATK4 phasing 结果的缺失位点不是 ./. 也不是 .|. 而是直接变成一个单独 ...