C++ Qt开发:Charts与数据库组件联动

打印 上一主题 下一主题

主题 893|帖子 893|积分 2679

Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍Charts组件与QSql数据库组件的常用方法及灵活运用。
在之前的文章中详细介绍了关于QCharts绘图组件的使用方式,本章将继续延续这个知识点,通过使用QSql数据库模块动态的读取某一个时间节点上的数据,当用户点击查询数据时则动态的输出该事件节点的所有数据,并将数据绘制到图形组件内,实现动态查询图形的功能。
首先我们需要生成一些测试数据,在文章课件中有一个InitDatabase案例,该案例中通过QSql组件动态创建一个Times表,该表中有三个字段分别记录了主机IP地址、时间、以及数据,并动态的想表中插入一些随机测试数据,读者可运行这段程序并等待十分钟以上,此时数据库database.sqlite3中将会出现如下所示的数据集;

再来看下主窗体是如何设计的,左侧使用一个ComboBox下拉选择框,右侧使用两个可自由调节的Date/TimeEdit组件,最底部则是一个graphicsView绘图组件,如下图;

由于涉及到IP地址的选择,所以在MainWindow主构造函数中我们需要对ComboBox组件进行初始化,在初始化时我们需要打开数据库并将数据库中的Times表,并查询到address字段,这里在查询语句中使用DISTINCT语句,该语句是用于在SQL查询中选择唯一值的关键字,它能够确保查询的结果集中每个列的值都是唯一的。
  1. SELECT DISTINCT address FROM Times;
复制代码
在代码中,上述查询的目的是从 "Times" 表中选择唯一的 "address" 列的值。如果 "Times" 表中有多个行具有相同的 "address" 值,DISTINCT 会确保在结果中只返回一个该值,以避免重复。
当具备了这条语句那么查询唯一值将变得非常容易,当查询到对应值只有只需要通过comboBox->addItem即可将唯一的IP地址追加到组件中,如下代码所示;
  1. MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
  2. {
  3.     ui->setupUi(this);
  4.     // 初始化绘图
  5.     InitLineChart();
  6.     // 初始化时间组件
  7.     QDateTime curDateTime = QDateTime::currentDateTime();
  8.     // 设置当前时间
  9.     ui->dateTimeEdit_Start->setDateTime(curDateTime);
  10.     ui->dateTimeEdit_End->setDateTime(curDateTime);
  11.     // 设置时间格式
  12.     ui->dateTimeEdit_Start->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
  13.     ui->dateTimeEdit_End->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
  14.     // 初始化数据库
  15.     db = QSqlDatabase::addDatabase("QSQLITE");
  16.     db.setDatabaseName("database.sqlite3");
  17.     if (!db.open())
  18.     {
  19.         std::cout << db.lastError().text().toStdString() << std::endl;
  20.         return;
  21.     }
  22.     // 查询数据库中的IP地址信息
  23.     QSqlQuery query;
  24.     if (query.exec("SELECT DISTINCT address FROM Times;"))
  25.     {
  26.         QSet<QString> uniqueAddresses;
  27.         while (query.next())
  28.         {
  29.             // Assuming 'address' is the name of the column
  30.             QString data_name = query.value(0).toString();
  31.             uniqueAddresses.insert(data_name);
  32.         }
  33.         // 清空现有的项
  34.         ui->comboBox->clear();
  35.         // 将唯一地址添加到 QComboBox 中
  36.         foreach (const QString &uniqueAddress, uniqueAddresses)
  37.         {
  38.             ui->comboBox->addItem(uniqueAddress);
  39.         }
  40.     }
  41.     else
  42.     {
  43.         std::cout << query.lastError().text().toStdString() << std::endl;
  44.     }
  45. }
复制代码
当界面中的按钮被点击后,事件触发时执行,其主要功能是从数据库中查询记录并根据用户在界面上选择的设备地址、起始时间和结束时间条件,筛选符合条件的数据,并将其显示在折线图中。
首先,获取折线图对象和数据库查询结果的指针,然后清空折线序列准备接收新的数据。通过遍历数据库查询结果,获取每条记录的字段值,同时获取用户输入的查询条件。计算时间差并限制查询范围在3600秒内,然后判断记录是否在指定的时间范围内,并将符合条件的数据点添加到折线序列中。如果查询范围超出定义,输出错误消息。
[code]void MainWindow:n_pushButton_clicked(){    // 获取指针    QLineSeries *series0=(QLineSeries *)ui->graphicsView_line->chart()->series().at(0);    // 清空图例    series0->clear();    // 查询数据    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 address_user = ui->comboBox->currentText();            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();            // 只允许查询小于3600秒的记录            uint sub_time = etime - stime;            if(sub_time = start_user_time.toStdString() &&                        date_time.toStdString()

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天津储鑫盛钢材现货供应商

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表