C/C++ Qt 數(shù)據(jù)庫(kù)與Chart歷史數(shù)據(jù)展示
在前面的博文中具體介紹了QChart組件是如何繪制各種通用的二維圖形的,本章內(nèi)容將繼續(xù)延申一個(gè)新的知識(shí)點(diǎn),通過(guò)數(shù)據(jù)庫(kù)存儲(chǔ)某一段時(shí)間節(jié)點(diǎn)數(shù)據(jù)的走向,當(dāng)用戶通過(guò)編輯框提交查詢記錄時(shí),程序自動(dòng)過(guò)濾出該時(shí)間節(jié)點(diǎn)下所有的數(shù)據(jù),并將該數(shù)據(jù)動(dòng)態(tài)繪制到圖形組件內(nèi),實(shí)現(xiàn)動(dòng)態(tài)查詢圖形的功能。
首先通過(guò)如下代碼,創(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ù)庫(kù) // 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ù)庫(kù)結(jié)構(gòu)如下:
接著編寫(xiě)一個(gè)模擬插入數(shù)據(jù)的案例,該案例每一秒向數(shù)據(jù)庫(kù)內(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í)行插入語(yǔ)句: " << 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ù)可以這樣寫(xiě)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ù)全部過(guò)濾出來(lái)了:
將過(guò)濾參數(shù)與QChart組件結(jié)合即可實(shí)現(xiàn)動(dòng)態(tài)繪圖效果,繪制UI界面如下:
當(dāng)用戶點(diǎn)擊查詢時(shí),直接從數(shù)據(jù)庫(kù)內(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ù)庫(kù) 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ù)庫(kù)與Chart歷史數(shù)據(jù)展示的詳細(xì)內(nèi)容,更多關(guān)于C++ Qt?的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言單雙線性及循環(huán)鏈表與實(shí)例
這篇文章主要介紹了C語(yǔ)言的單鏈表、雙鏈表和循環(huán)鏈表,還有一些相關(guān)的實(shí)例,感興趣的同學(xué)可以借鑒一下2023-03-03