C/C++ Qt 數(shù)據(jù)庫與Chart歷史數(shù)據(jù)展示
在前面的博文中具體介紹了QChart組件是如何繪制各種通用的二維圖形的,本章內(nèi)容將繼續(xù)延申一個(gè)新的知識(shí)點(diǎn),通過數(shù)據(jù)庫存儲(chǔ)某一段時(shí)間節(jié)點(diǎn)數(shù)據(jù)的走向,當(dāng)用戶通過編輯框提交查詢記錄時(shí),程序自動(dòng)過濾出該時(shí)間節(jié)點(diǎn)下所有的數(shù)據(jù),并將該數(shù)據(jù)動(dòng)態(tài)繪制到圖形組件內(nèi),實(shí)現(xiàn)動(dòng)態(tài)查詢圖形的功能。
首先通過如下代碼,創(chuàng)建Times表,表內(nèi)記錄有某個(gè)主機(jī)某個(gè)時(shí)間節(jié)點(diǎn)下的數(shù)值:
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <iostream>
#include <QStringList>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QDateTime>
#include <QTime>
// 初始化數(shù)據(jù)庫
// 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;
}
// 執(zhí)行SQL創(chuàng)建表
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();
}
數(shù)據(jù)庫結(jié)構(gòu)如下:

接著編寫一個(gè)模擬插入數(shù)據(jù)的案例,該案例每一秒向數(shù)據(jù)庫內(nèi)插入一條記錄,我們運(yùn)行一段時(shí)間。
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <iostream>
#include <QStringList>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QDateTime>
#include <QTime>
// 延時(shí)函數(shù)
void Sleep(int msec)
{
QTime dieTime = QTime::currentTime().addMSecs(msec);
while(QTime::currentTime() < dieTime)
QCoreApplication::processEvents(QEventLoop::AllEvents,100);
}
// 生成隨機(jī)數(shù)
int GetRandom()
{
int num = qrand() % 100;
return num;
}
// 插入數(shù)據(jù)
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 << "執(zhí)行插入語句: " << 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();
}
運(yùn)行插入程序,統(tǒng)計(jì)一段時(shí)間 從 2021-12-11 15:34:16 到 2021-12-11 15:40:04 停止,表內(nèi)記錄如下:

如果我們需要查詢某一個(gè)時(shí)間節(jié)點(diǎn)下的數(shù)據(jù),例如查詢2021-12-11 15:35:00 - 2021-12-11 15:37:00的數(shù)據(jù)可以這樣寫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>
// 輸出數(shù)據(jù)
// 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;
}
// 查詢數(shù)據(jù)
QSqlQuery query("SELECT * FROM Times;",db);
QSqlRecord rec = query.record();
// 循環(huán)所有記錄
while(query.next())
{
// 判斷當(dāng)前記錄是否有效
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();
}
這樣就可以將該區(qū)間內(nèi)所有的數(shù)據(jù)全部過濾出來了:

將過濾參數(shù)與QChart組件結(jié)合即可實(shí)現(xiàn)動(dòng)態(tài)繪圖效果,繪制UI界面如下:

當(dāng)用戶點(diǎn)擊查詢時(shí),直接從數(shù)據(jù)庫內(nèi)取出數(shù)據(jù),并將其動(dòng)態(tài)更新到Chart組件內(nèi)即可,實(shí)現(xiàn)代碼如下:
#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()
{
// 創(chuàng)建圖表的各個(gè)部件
QChart *chart = new QChart();
// 將Chart添加到ChartView
ui->graphicsView->setChart(chart);
ui->graphicsView->setRenderHint(QPainter::Antialiasing);
// 隱藏圖例
chart->legend()->hide();
// 設(shè)置圖表主題色
ui->graphicsView->chart()->setTheme(QChart::ChartTheme(1));
// 創(chuàng)建曲線序列
QLineSeries *series0 = new QLineSeries();
// 序列添加到圖表
chart->addSeries(series0);
// 創(chuàng)建坐標(biāo)軸
QValueAxis *axisX = new QValueAxis; // X軸
axisX->setRange(1, 100); // 設(shè)置坐標(biāo)軸范圍
axisX->setLabelFormat("%d %"); // 設(shè)置X軸格式
axisX->setMinorTickCount(5); // 設(shè)置X軸刻度
QValueAxis *axisY = new QValueAxis; // Y軸
axisY->setRange(0, 100); // Y軸范圍
axisY->setMinorTickCount(4); // s設(shè)置Y軸刻度
// 設(shè)置X于Y軸數(shù)據(jù)集
chart->setAxisX(axisX, series0); // 為序列設(shè)置坐標(biāo)軸
chart->setAxisY(axisY, series0);
}
// 為序列生成數(shù)據(jù)
void MainWindow::SetData()
{
// 獲取指針
QLineSeries *series0=(QLineSeries *)ui->graphicsView->chart()->series().at(0);
// 清空?qǐng)D例
series0->clear();
// 鏈接數(shù)據(jù)庫
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("lyshark.db");
if (!db.open())
{
return;
}
// 查詢數(shù)據(jù)
QSqlQuery query("SELECT * FROM Times;",db);
QSqlRecord rec = query.record();
// 賦予數(shù)據(jù)
qreal t=0,intv=1;
// 循環(huán)所有記錄
while(query.next())
{
// 判斷當(dāng)前記錄是否有效
// 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();
// 將時(shí)間字符串轉(zhuǎn)為秒,并計(jì)算差值 (秒為單位)
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)
{
// 查詢指定區(qū)間內(nèi)的數(shù)據(jù)
if(date_time.toStdString() >= start_user_time.toStdString() && date_time.toStdString() <= end_user_time.toStdString())
{
// std::cout << "區(qū)間內(nèi)的數(shù)據(jù): " << 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();
// 初始化時(shí)間組件
QDateTime curDateTime = QDateTime::currentDateTime();
// 設(shè)置當(dāng)前時(shí)間
ui->dateTimeEdit_Start->setDateTime(curDateTime);
ui->dateTimeEdit_End->setDateTime(curDateTime);
// 設(shè)置時(shí)間格式
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 數(shù)據(jù)庫與Chart歷史數(shù)據(jù)展示的詳細(xì)內(nèi)容,更多關(guān)于C++ Qt?的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++消息隊(duì)列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收)
這篇文章主要介紹了C++消息隊(duì)列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收),消息隊(duì)列是一種先進(jìn)先出的隊(duì)列型數(shù)據(jù)結(jié)構(gòu),實(shí)際上是系統(tǒng)內(nèi)核中的一個(gè)內(nèi)部鏈表2022-08-08
深入學(xué)習(xí)C++智能指針之shared_ptr與右值引用的方法
智能指針的核心實(shí)現(xiàn)技術(shù)是引用計(jì)數(shù),每使用它一次,內(nèi)部引用計(jì)數(shù)加1,每析構(gòu)一次內(nèi)部的引用計(jì)數(shù)減1,減為0時(shí),刪除所指向的堆內(nèi)存,今天通過本文給大家分享C++智能指針之shared_ptr與右值引用的方法,需要的朋友跟隨小編一起看看吧2021-07-07
深入探討C語言中局部變量與全局變量在內(nèi)存中的存放位置
本篇文章是對(duì)在C語言中局部變量與全局變量在內(nèi)存中的存放位置進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C語言實(shí)現(xiàn)考試報(bào)名管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)考試報(bào)名管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
基于Matlab實(shí)現(xiàn)人工神經(jīng)網(wǎng)絡(luò)(ANN)回歸的示例詳解
這篇文章主要為大家詳細(xì)介紹了Matlab實(shí)現(xiàn)人工神經(jīng)網(wǎng)絡(luò)(ANN)回歸的相關(guān)資料,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-02-02
解析Linux下的時(shí)間函數(shù):設(shè)置以及獲取時(shí)間的方法
本篇文章是對(duì)Linux下的時(shí)間函數(shù):設(shè)置以及獲取時(shí)間的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C語言實(shí)現(xiàn)實(shí)驗(yàn)設(shè)備管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)實(shí)驗(yàn)設(shè)備管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06

