经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C/C++ Qt 数据库与Chart实现历史数据展示
来源:cnblogs  作者:lyshark  时间:2021/12/15 9:07:52  对本文有异议

在前面的博文中具体介绍了QChart组件是如何绘制各种通用的二维图形的,本章内容将继续延申一个新的知识点,通过数据库存储某一段时间节点数据的走向,当用户通过编辑框提交查询记录时,程序自动过滤出该时间节点下所有的数据,并将该数据动态绘制到图形组件内,实现动态查询图形的功能。

首先通过如下代码,创建Times表,表内记录有某个主机某个时间节点下的数值:

  1. #include <QCoreApplication>
  2. #include <QSqlDatabase>
  3. #include <QSqlError>
  4. #include <QSqlQuery>
  5. #include <QSqlRecord>
  6. #include <iostream>
  7. #include <QStringList>
  8. #include <QString>
  9. #include <QVariant>
  10. #include <QDebug>
  11. #include <QDateTime>
  12. #include <QTime>
  13. // 初始化数据库
  14. // https://www.cnblogs.com/lyshark
  15. void InitSql()
  16. {
  17. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
  18. db.setDatabaseName("lyshark.db");
  19. if (!db.open())
  20. {
  21. std::cout << db.lastError().text().toStdString()<< std::endl;
  22. return;
  23. }
  24. // 执行SQL创建表
  25. db.exec("DROP TABLE Times");
  26. db.exec("CREATE TABLE Times ("
  27. "id INTEGER PRIMARY KEY AUTOINCREMENT, "
  28. "address VARCHAR(64) NOT NULL, "
  29. "datetime VARCHAR(128) NOT NULL, "
  30. "value INTEGER NOT NULL"
  31. ")"
  32. );
  33. db.commit();
  34. db.close();
  35. }
  36. int main(int argc, char *argv[])
  37. {
  38. QCoreApplication a(argc, argv);
  39. InitSql();
  40. return a.exec();
  41. }

数据库结构如下:

接着编写一个模拟插入数据的案例,该案例每一秒向数据库内插入一条记录,我们运行一段时间。

  1. #include <QCoreApplication>
  2. #include <QSqlDatabase>
  3. #include <QSqlError>
  4. #include <QSqlQuery>
  5. #include <QSqlRecord>
  6. #include <iostream>
  7. #include <QStringList>
  8. #include <QString>
  9. #include <QVariant>
  10. #include <QDebug>
  11. #include <QDateTime>
  12. #include <QTime>
  13. // 延时函数
  14. void Sleep(int msec)
  15. {
  16. QTime dieTime = QTime::currentTime().addMSecs(msec);
  17. while(QTime::currentTime() < dieTime)
  18. QCoreApplication::processEvents(QEventLoop::AllEvents,100);
  19. }
  20. // 生成随机数
  21. int GetRandom()
  22. {
  23. int num = qrand() % 100;
  24. return num;
  25. }
  26. // 插入数据
  27. void InsertSQL()
  28. {
  29. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
  30. db.setDatabaseName("lyshark.db");
  31. if (!db.open())
  32. {
  33. std::cout << db.lastError().text().toStdString()<< std::endl;
  34. return;
  35. }
  36. for(int index=0;index <99999;index++)
  37. {
  38. QString address = QString("192.168.1.100");
  39. QDateTime curDateTime = QDateTime::currentDateTime();
  40. QString date_time = curDateTime.toString("yyyy-MM-dd hh:mm:ss");
  41. int value = GetRandom();
  42. QString run_sql = QString("INSERT INTO Times(id,address,datetime,value) VALUES (%1,'%2','%3',%4);")
  43. .arg(index).arg(address).arg(date_time).arg(value);
  44. std::cout << "执行插入语句: " << run_sql.toStdString() << std::endl;
  45. db.exec(run_sql);
  46. db.commit();
  47. Sleep(1000);
  48. }
  49. db.close();
  50. }
  51. int main(int argc, char *argv[])
  52. {
  53. QCoreApplication a(argc, argv);
  54. qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
  55. InsertSQL();
  56. return a.exec();
  57. }

运行插入程序,统计一段时间 从 2021-12-11 15:34:162021-12-11 15:40:04 停止,表内记录如下:

如果我们需要查询某一个时间节点下的数据,例如查询2021-12-11 15:35:00 - 2021-12-11 15:37:00的数据可以这样写SQL:

  1. #include <QCoreApplication>
  2. #include <QSqlDatabase>
  3. #include <QSqlError>
  4. #include <QSqlQuery>
  5. #include <QSqlRecord>
  6. #include <iostream>
  7. #include <QStringList>
  8. #include <QString>
  9. #include <QVariant>
  10. #include <QDebug>
  11. #include <QDateTime>
  12. #include <QTime>
  13. // 输出数据
  14. // https://www.cnblogs.com/lyshark
  15. void SelectSQL()
  16. {
  17. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
  18. db.setDatabaseName("lyshark.db");
  19. if (!db.open())
  20. {
  21. std::cout << db.lastError().text().toStdString()<< std::endl;
  22. return;
  23. }
  24. // 查询数据
  25. QSqlQuery query("SELECT * FROM Times;",db);
  26. QSqlRecord rec = query.record();
  27. // 循环所有记录
  28. while(query.next())
  29. {
  30. // 判断当前记录是否有效
  31. if(query.isValid())
  32. {
  33. int id_value = query.value(rec.indexOf("id")).toInt();
  34. QString address_value = query.value(rec.indexOf("address")).toString();
  35. QString date_time = query.value(rec.indexOf("datetime")).toString();
  36. int this_value = query.value(rec.indexOf("value")).toInt();
  37. if(date_time.toStdString() >= "2021-12-11 15:35:00" && date_time.toStdString() <="2021-12-11 15:37:00")
  38. {
  39. std::cout << "value: " << this_value << std::endl;
  40. }
  41. }
  42. }
  43. }
  44. int main(int argc, char *argv[])
  45. {
  46. QCoreApplication a(argc, argv);
  47. SelectSQL();
  48. return a.exec();
  49. }

这样就可以将该区间内所有的数据全部过滤出来了:

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

当用户点击查询时,直接从数据库内取出数据,并将其动态更新到Chart组件内即可,实现代码如下:

  1. #include <QSqlDatabase>
  2. #include <QSqlError>
  3. #include <QSqlQuery>
  4. #include <QSqlRecord>
  5. #include <iostream>
  6. #include <QStringList>
  7. #include <QString>
  8. #include <QVariant>
  9. #include <QDebug>
  10. #include <QDateTime>
  11. #include <QTime>
  12. // 初始化Chart图表
  13. void MainWindow::InitChart()
  14. {
  15. // 创建图表的各个部件
  16. QChart *chart = new QChart();
  17. // 将Chart添加到ChartView
  18. ui->graphicsView->setChart(chart);
  19. ui->graphicsView->setRenderHint(QPainter::Antialiasing);
  20. // 隐藏图例
  21. chart->legend()->hide();
  22. // 设置图表主题色
  23. ui->graphicsView->chart()->setTheme(QChart::ChartTheme(1));
  24. // 创建曲线序列
  25. QLineSeries *series0 = new QLineSeries();
  26. // 序列添加到图表
  27. chart->addSeries(series0);
  28. // 创建坐标轴
  29. QValueAxis *axisX = new QValueAxis; // X轴
  30. axisX->setRange(1, 100); // 设置坐标轴范围
  31. axisX->setLabelFormat("%d %"); // 设置X轴格式
  32. axisX->setMinorTickCount(5); // 设置X轴刻度
  33. QValueAxis *axisY = new QValueAxis; // Y轴
  34. axisY->setRange(0, 100); // Y轴范围
  35. axisY->setMinorTickCount(4); // s设置Y轴刻度
  36. // 设置X于Y轴数据集
  37. chart->setAxisX(axisX, series0); // 为序列设置坐标轴
  38. chart->setAxisY(axisY, series0);
  39. }
  40. // 为序列生成数据
  41. void MainWindow::SetData()
  42. {
  43. // 获取指针
  44. QLineSeries *series0=(QLineSeries *)ui->graphicsView->chart()->series().at(0);
  45. // 清空图例
  46. series0->clear();
  47. // 链接数据库
  48. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
  49. db.setDatabaseName("lyshark.db");
  50. if (!db.open())
  51. {
  52. return;
  53. }
  54. // 查询数据
  55. QSqlQuery query("SELECT * FROM Times;",db);
  56. QSqlRecord rec = query.record();
  57. // 赋予数据
  58. qreal t=0,intv=1;
  59. // 循环所有记录
  60. while(query.next())
  61. {
  62. // 判断当前记录是否有效
  63. // https://www.cnblogs.com/lyshark
  64. if(query.isValid())
  65. {
  66. QString address_value = query.value(rec.indexOf("address")).toString();
  67. QString date_time = query.value(rec.indexOf("datetime")).toString();
  68. int this_value = query.value(rec.indexOf("value")).toInt();
  69. // 获取组件字符串
  70. QString start_user_time = ui->dateTimeEdit_Start->text();
  71. QString end_user_time = ui->dateTimeEdit_End->text();
  72. // 将时间字符串转为秒,并计算差值 (秒为单位)
  73. QDateTime start_timet = QDateTime::fromString(start_user_time, "yyyy-MM-dd hh:mm:ss");
  74. QDateTime end_timet = QDateTime::fromString(end_user_time, "yyyy-MM-dd hh:mm:ss");
  75. uint stime = start_timet.toTime_t();
  76. uint etime = end_timet.toTime_t();
  77. // 只允许查询小于180秒的记录
  78. uint sub_time = etime - stime;
  79. if(sub_time <= 180)
  80. {
  81. // 查询指定区间内的数据
  82. if(date_time.toStdString() >= start_user_time.toStdString() && date_time.toStdString() <= end_user_time.toStdString())
  83. {
  84. // std::cout << "区间内的数据: " << this_value << std::endl;
  85. series0->append(t,this_value);
  86. t+=intv;
  87. }
  88. }
  89. else
  90. {
  91. std::cout << "查询范围超出定义." << std::endl;
  92. return;
  93. }
  94. }
  95. }
  96. }
  97. // 将添加的widget控件件提升为QChartView类
  98. MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
  99. {
  100. ui->setupUi(this);
  101. InitChart();
  102. // 初始化时间组件
  103. QDateTime curDateTime = QDateTime::currentDateTime();
  104. // 设置当前时间
  105. ui->dateTimeEdit_Start->setDateTime(curDateTime);
  106. ui->dateTimeEdit_End->setDateTime(curDateTime);
  107. // 设置时间格式
  108. ui->dateTimeEdit_Start->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
  109. ui->dateTimeEdit_End->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
  110. }
  111. MainWindow::~MainWindow()
  112. {
  113. delete ui;
  114. }
  115. void MainWindow::on_pushButton_clicked()
  116. {
  117. SetData();
  118. }

查询效果如下所示:


版权声明: 本博客文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章 [均为原创] 作品,转载请 [添加出处] ,您添加出处是我创作的动力!

本博客所有文章除参考文献特别声明外,均采用 知识共享 署名-非商业性使用 [CC BY-NC-ND 4.0] 国际许可协议,请遵循协议许可

警告:如果您恶意转载本人文章并被本人发现,则您的整站文章,将会变为我的原创作品,请相互尊重 !

原文链接:http://www.cnblogs.com/LyShark/p/15675743.html

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号