在前面的博文中具体介绍了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>
void InitSql() { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("lyshark.db"); if (!db.open()) { std::cout << db.lastError().text().toStdString()<< std::endl; return; }
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>
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>
void MainWindow::InitChart() { QChart *chart = new QChart();
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; axisX->setRange(1, 100); axisX->setLabelFormat("%d %"); axisX->setMinorTickCount(5);
QValueAxis *axisY = new QValueAxis; axisY->setRange(0, 100); axisY->setMinorTickCount(4);
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()) { 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();
uint sub_time = etime - stime; if(sub_time <= 180) { if(date_time.toStdString() >= start_user_time.toStdString() && date_time.toStdString() <= end_user_time.toStdString()) { series0->append(t,this_value); t+=intv; } } else { std::cout << "查询范围超出定义." << std::endl; return; } } } }
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(); }
|
查询效果如下所示:
