C++ Qt开发:Charts与数据库组件联动
Qt 是一個(gè)跨平臺(tái)C++圖形界面開發(fā)庫,利用Qt可以快速開發(fā)跨平臺(tái)窗體應(yīng)用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實(shí)現(xiàn)圖形化開發(fā)極大的方便了開發(fā)效率,本章將重點(diǎn)介紹Charts組件與QSql數(shù)據(jù)庫組件的常用方法及靈活運(yùn)用。
在之前的文章中詳細(xì)介紹了關(guān)于QCharts繪圖組件的使用方式,本章將繼續(xù)延續(xù)這個(gè)知識(shí)點(diǎn),通過使用QSql數(shù)據(jù)庫模塊動(dòng)態(tài)的讀取某一個(gè)時(shí)間節(jié)點(diǎn)上的數(shù)據(jù),當(dāng)用戶點(diǎn)擊查詢數(shù)據(jù)時(shí)則動(dòng)態(tài)的輸出該事件節(jié)點(diǎn)的所有數(shù)據(jù),并將數(shù)據(jù)繪制到圖形組件內(nèi),實(shí)現(xiàn)動(dòng)態(tài)查詢圖形的功能。
首先我們需要生成一些測(cè)試數(shù)據(jù),在文章課件中有一個(gè)InitDatabase案例,該案例中通過QSql組件動(dòng)態(tài)創(chuàng)建一個(gè)Times表,該表中有三個(gè)字段分別記錄了主機(jī)IP地址、時(shí)間、以及數(shù)據(jù),并動(dòng)態(tài)的想表中插入一些隨機(jī)測(cè)試數(shù)據(jù),讀者可運(yùn)行這段程序并等待十分鐘以上,此時(shí)數(shù)據(jù)庫database.sqlite3中將會(huì)出現(xiàn)如下所示的數(shù)據(jù)集;
再來看下主窗體是如何設(shè)計(jì)的,左側(cè)使用一個(gè)ComboBox下拉選擇框,右側(cè)使用兩個(gè)可*調(diào)節(jié)的Date/TimeEdit組件,最底部則是一個(gè)graphicsView繪圖組件,如下圖;
由于涉及到IP地址的選擇,所以在MainWindow主構(gòu)造函數(shù)中我們需要對(duì)ComboBox組件進(jìn)行初始化,在初始化時(shí)我們需要打開數(shù)據(jù)庫并將數(shù)據(jù)庫中的Times表,并查詢到address字段,這里在查詢語句中使用DISTINCT語句,該語句是用于在SQL查詢中選擇唯一值的關(guān)鍵字,它能夠確保查詢的結(jié)果集中每個(gè)列的值都是唯一的。
SELECT DISTINCT address FROM Times;
在代碼中,上述查詢的目的是從 "Times" 表中選擇唯一的 "address" 列的值。如果 "Times" 表中有多個(gè)行具有相同的 "address" 值,DISTINCT 會(huì)確保在結(jié)果中只返回一個(gè)該值,以避免重復(fù)。
當(dāng)具備了這條語句那么查詢唯一值將變得非常容易,當(dāng)查詢到對(duì)應(yīng)值只有只需要通過comboBox->addItem即可將唯一的IP地址追加到組件中,如下代碼所示;
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 初始化繪圖
InitLineChart();
// 初始化時(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");
// 初始化數(shù)據(jù)庫
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("database.sqlite3");
if (!db.open())
{
std::cout << db.lastError().text().toStdString() << std::endl;
return;
}
// 查詢數(shù)據(jù)庫中的IP地址信息
QSqlQuery query;
if (query.exec("SELECT DISTINCT address FROM Times;"))
{
QSet<QString> uniqueAddresses;
while (query.next())
{
// Assuming 'address' is the name of the column
QString data_name = query.value(0).toString();
uniqueAddresses.insert(data_name);
}
// 清空現(xiàn)有的項(xiàng)
ui->comboBox->clear();
// 將唯一地址添加到 QComboBox 中
foreach (const QString &uniqueAddress, uniqueAddresses)
{
ui->comboBox->addItem(uniqueAddress);
}
}
else
{
std::cout << query.lastError().text().toStdString() << std::endl;
}
}
接著來看下如何實(shí)現(xiàn)InitLineChart()繪圖函數(shù),繪圖部分由于我們不需要直接繪制所以這里可以先初始化折線圖表,等待后期添加數(shù)據(jù)繪制即可,這段代碼的實(shí)現(xiàn)如下所示;
首先,創(chuàng)建一個(gè)QChart對(duì)象,代表整個(gè)圖表,并將其添加到QGraphicsView中。隨后,通過隱藏圖例提高圖表的美觀度。接著,創(chuàng)建一個(gè)QLineSeries對(duì)象,表示折線圖中的數(shù)據(jù)序列,并將其添加到圖表中。為確保正確顯示,創(chuàng)建了X軸和Y軸的坐標(biāo)軸對(duì)象,并設(shè)置了范圍、格式和刻度。最后,將X軸和Y軸與折線序列關(guān)聯(lián),以便在圖表中顯示數(shù)據(jù)。這段代碼實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的折線圖的初始化,為進(jìn)一步添加和展示數(shù)據(jù)提供了基礎(chǔ)。
// 初始化Chart圖表
void MainWindow::InitLineChart()
{
// 創(chuàng)建圖表的各個(gè)部件
QChart *chart = new QChart();
// 將Chart添加到ChartView
ui->graphicsView_line->setChart(chart);
ui->graphicsView_line->setRenderHint(QPainter::Antialiasing);
// 隱藏圖例
chart->legend()->hide();
// 創(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);
}
當(dāng)界面中的按鈕被點(diǎn)擊后,事件觸發(fā)時(shí)執(zhí)行,其主要功能是從數(shù)據(jù)庫中查詢記錄并根據(jù)用戶在界面上選擇的設(shè)備地址、起始時(shí)間和結(jié)束時(shí)間條件,篩選符合條件的數(shù)據(jù),并將其顯示在折線圖中。
首先,獲取折線圖對(duì)象和數(shù)據(jù)庫查詢結(jié)果的指針,然后清空折線序列準(zhǔn)備接收新的數(shù)據(jù)。通過遍歷數(shù)據(jù)庫查詢結(jié)果,獲取每條記錄的字段值,同時(shí)獲取用戶輸入的查詢條件。計(jì)算時(shí)間差并限制查詢范圍在3600秒內(nèi),然后判斷記錄是否在指定的時(shí)間范圍內(nèi),并將符合條件的數(shù)據(jù)點(diǎn)添加到折線序列中。如果查詢范圍超出定義,輸出錯(cuò)誤消息。
void MainWindow::on_pushButton_clicked()
{
// 獲取指針
QLineSeries *series0=(QLineSeries *)ui->graphicsView_line->chart()->series().at(0);
// 清空?qǐng)D例
series0->clear();
// 查詢數(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)前記錄是否有效
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 address_user = ui->comboBox->currentText();
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();
// 只允許查詢小于3600秒的記錄
uint sub_time = etime - stime;
if(sub_time <= 3600)
{
// 查詢指定區(qū)間內(nèi)的數(shù)據(jù)
if(date_time.toStdString() >= start_user_time.toStdString() &&
date_time.toStdString() <= end_user_time.toStdString() &&
address_value == address_user
)
{
// std::cout << "區(qū)間內(nèi)的數(shù)據(jù): " << this_value << std::endl;
series0->append(t,this_value);
t+=intv;
}
}
else
{
std::cout << "查詢范圍超出定義." << std::endl;
return;
}
}
}
}
這段代碼實(shí)現(xiàn)了通過用戶輸入條件查詢數(shù)據(jù)庫,并動(dòng)態(tài)更新折線圖的功能,用于在界面上顯示符合條件的數(shù)據(jù)趨勢(shì)。
至此數(shù)據(jù)庫與繪圖組件的聯(lián)動(dòng)效果就實(shí)現(xiàn)了,其實(shí)很容易理解,因?yàn)槭且粋€(gè)案例并沒有包含任何復(fù)雜的功能這也是為了方便功能的展示,讀者可自行運(yùn)行并查詢一個(gè)區(qū)間內(nèi)的折線圖,如下所示;
總結(jié)
以上是生活随笔為你收集整理的C++ Qt开发:Charts与数据库组件联动的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android对接华为AI - 文本识别
- 下一篇: 阿里云DMS添加ECS自建数据库