QT C++ 利用 double key = QTime::currentTime(); 获取当前时间到当天经历的总秒数
时间: 2024-10-21 07:05:15 浏览: 73
在Qt C++中,如果你想获取当前时间到当天开始以来经过的总秒数,可以使用`QDateTime`类配合`QDate`类。首先,获取当前时间和日期,然后从这两个对象中计算差值。以下是示例代码:
```cpp
#include <QDateTime>
#include <QDate>
int main()
{
// 获取当前时间
QDateTime currentTime = QDateTime::currentDateTime();
// 创建今天的开始时间
QDate currentDate = QDate::currentDate();
QDateTime startDate = QDateTime(currentDate, currentDateTime().timeZone());
// 计算两个时间之间的秒数差
int totalSeconds = (currentTime.toSecsSinceEpoch() - startDate.toSecsSinceEpoch()) / 1000;
qDebug() << "总秒数: " << totalSeconds;
return 0;
}
```
在这个例子中,我们先获取了当前的日期和时间(`QDateTime`),然后创建了一个表示今天开始的时间(只包含日期部分)。接着,我们将这两个时间转换为自Unix epoch(1970年1月1日 00:00:00 UTC)以来的秒数,然后相减得到总秒数。
相关问题
多个通道采集的数据存放到数据库,然后把数据在取出来放到数组,丛数组里取数据进行绘制曲线图,要实现随时间变化形成动态图,并且要实现可以选择某个通道的某个传感器的数据进行曲线图的显示,写一个使用qt6.2 c++实现的例子,尽可能详细,并且有注释
好的,以下是一个使用Qt6.2 C++实现的例子,实现多个通道数据存放到数据库,绘制曲线图并实现动态图以及选择某个通道的某个传感器的数据进行曲线图的显示。
1. 创建Qt项目
首先创建一个Qt Widgets Application项目,并在项目中包含Qt Charts模块。
2. 设计UI界面
在Qt Designer中设计一个简单的UI界面,包括一个QComboBox用于选择通道和传感器,一个QChartView用于显示曲线图,一个QPushButton用于开始/停止动态图的绘制,以及一些QLabel和QLineEdit用于显示和输入一些信息。
3. 创建数据库
使用Qt提供的QSqlDatabase类连接到SQLite数据库,并创建一个名为"sensor_data.db"的数据库。可以在程序启动时创建数据库,也可以事先用SQLite Studio等工具创建好数据库。
```c++
#include <QtSql>
// 创建数据库连接
QSqlDatabase db;
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("sensor_data.db");
// 打开数据库
if (!db.open()) {
qDebug() << "Failed to open database!";
return;
}
// 创建数据表
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS SensorData ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"channel INTEGER NOT NULL, "
"sensor INTEGER NOT NULL, "
"value REAL NOT NULL, "
"timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
```
4. 采集数据并存入数据库
使用Qt提供的QSerialPort类或其他方式采集传感器数据,并将数据存入数据库中。下面是一个简单的示例代码:
```c++
// 假设采集到了一个数据,数据来自通道1的传感器2,数值为3.14
int channel = 1;
int sensor = 2;
double value = 3.14;
// 将数据插入到数据库中
QSqlQuery query;
query.prepare("INSERT INTO SensorData (channel, sensor, value) VALUES (:channel, :sensor, :value)");
query.bindValue(":channel", channel);
query.bindValue(":sensor", sensor);
query.bindValue(":value", value);
query.exec();
```
可以将采集数据的代码放入一个线程中进行,以避免阻塞主线程。
5. 从数据库中取出数据并绘制曲线图
使用Qt Charts模块绘制曲线图,可以先从数据库中取出所有数据,然后根据选择的通道和传感器过滤数据,并将数据添加到曲线图中。下面是一个简单的示例代码:
```c++
// 创建曲线图
QChart *chart = new QChart();
chart->setTitle("Sensor Data");
// 创建坐标轴
QValueAxis *axisX = new QValueAxis();
axisX->setTitleText("Time");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis();
axisY->setTitleText("Value");
chart->addAxis(axisY, Qt::AlignLeft);
// 从数据库中取出数据
QSqlQuery query;
query.exec("SELECT * FROM SensorData");
// 遍历数据并添加到曲线图中
while (query.next()) {
int channel = query.value("channel").toInt();
int sensor = query.value("sensor").toInt();
double value = query.value("value").toDouble();
QDateTime timestamp = query.value("timestamp").toDateTime();
// 只添加选择的通道和传感器的数据
if (channel == selectedChannel && sensor == selectedSensor) {
QLineSeries *series = new QLineSeries();
series->append(timestamp.toMSecsSinceEpoch(), value);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
}
}
// 显示曲线图
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
ui->chartLayout->addWidget(chartView);
```
6. 实现动态图
在上述代码的基础上,可以使用Qt提供的QTimer类定时取出最新的数据并添加到曲线图中,实现动态图的效果。下面是一个简单的示例代码:
```c++
// 创建QTimer对象
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [=]() {
// 从数据库中取出最新的数据
QSqlQuery query;
query.exec("SELECT * FROM SensorData ORDER BY timestamp DESC LIMIT 1");
query.next();
int channel = query.value("channel").toInt();
int sensor = query.value("sensor").toInt();
double value = query.value("value").toDouble();
QDateTime timestamp = query.value("timestamp").toDateTime();
// 只添加选择的通道和传感器的数据
if (channel == selectedChannel && sensor == selectedSensor) {
// 遍历曲线图的系列并找到对应的系列
QList<QAbstractSeries *> seriesList = chart->series();
for (int i = 0; i < seriesList.size(); ++i) {
QLineSeries *series = qobject_cast<QLineSeries *>(seriesList.at(i));
if (series->name() == QString("%1-%2").arg(channel).arg(sensor)) {
// 在系列末尾添加新的数据点
series->append(timestamp.toMSecsSinceEpoch(), value);
break;
}
}
}
});
timer->start(1000); // 每秒钟更新一次
```
7. 实现选择通道和传感器的功能
使用QComboBox和信号槽机制,实现选择通道和传感器的功能。下面是一个简单的示例代码:
```c++
// 创建QComboBox对象并添加选项
QComboBox *channelComboBox = new QComboBox();
channelComboBox->addItem("Channel 1", 1);
channelComboBox->addItem("Channel 2", 2);
connect(channelComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index) {
selectedChannel = channelComboBox->currentData().toInt();
updateChart(); // 更新曲线图
});
ui->channelLayout->addWidget(channelComboBox);
QComboBox *sensorComboBox = new QComboBox();
sensorComboBox->addItem("Sensor 1", 1);
sensorComboBox->addItem("Sensor 2", 2);
connect(sensorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index) {
selectedSensor = sensorComboBox->currentData().toInt();
updateChart(); // 更新曲线图
});
ui->sensorLayout->addWidget(sensorComboBox);
```
其中,selectedChannel和selectedSensor是类成员变量,表示当前选择的通道和传感器。
8. 完整代码
以下是一个完整的示例代码,包括采集数据、存入数据库、绘制曲线图、实现动态图和选择通道和传感器的功能。需要注意的是,这只是一个简单的示例代码,实际应用中需要更加完善和健壮。
```c++
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QtCharts>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 连接到数据库并创建数据表
QSqlDatabase db;
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("sensor_data.db");
if (!db.open()) {
qDebug() << "Failed to open database!";
return;
}
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS SensorData ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"channel INTEGER NOT NULL, "
"sensor INTEGER NOT NULL, "
"value REAL NOT NULL, "
"timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
// 创建QComboBox对象并添加选项
QComboBox *channelComboBox = new QComboBox();
channelComboBox->addItem("Channel 1", 1);
channelComboBox->addItem("Channel 2", 2);
connect(channelComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index) {
selectedChannel = channelComboBox->currentData().toInt();
updateChart(); // 更新曲线图
});
ui->channelLayout->addWidget(channelComboBox);
QComboBox *sensorComboBox = new QComboBox();
sensorComboBox->addItem("Sensor 1", 1);
sensorComboBox->addItem("Sensor 2", 2);
connect(sensorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index) {
selectedSensor = sensorComboBox->currentData().toInt();
updateChart(); // 更新曲线图
});
ui->sensorLayout->addWidget(sensorComboBox);
// 创建曲线图
chart = new QChart();
chart->setTitle("Sensor Data");
// 创建坐标轴
axisX = new QValueAxis();
axisX->setTitleText("Time");
chart->addAxis(axisX, Qt::AlignBottom);
axisY = new QValueAxis();
axisY->setTitleText("Value");
chart->addAxis(axisY, Qt::AlignLeft);
// 显示曲线图
chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
ui->chartLayout->addWidget(chartView);
// 创建QTimer对象
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [=]() {
// 从数据库中取出最新的数据
QSqlQuery query;
query.exec("SELECT * FROM SensorData ORDER BY timestamp DESC LIMIT 1");
query.next();
int channel = query.value("channel").toInt();
int sensor = query.value("sensor").toInt();
double value = query.value("value").toDouble();
QDateTime timestamp = query.value("timestamp").toDateTime();
// 只添加选择的通道和传感器的数据
if (channel == selectedChannel && sensor == selectedSensor) {
// 遍历曲线图的系列并找到对应的系列
QList<QAbstractSeries *> seriesList = chart->series();
for (int i = 0; i < seriesList.size(); ++i) {
QLineSeries *series = qobject_cast<QLineSeries *>(seriesList.at(i));
if (series->name() == QString("%1-%2").arg(channel).arg(sensor)) {
// 在系列末尾添加新的数据点
series->append(timestamp.toMSecsSinceEpoch(), value);
break;
}
}
}
});
// 开始采集数据
startDataCollection();
}
MainWindow::~MainWindow()
{
// 停止采集数据
stopDataCollection();
delete ui;
}
void MainWindow::startDataCollection()
{
// 开始采集数据的线程
dataThread = new QThread(this);
dataThread->start();
connect(dataThread, &QThread::finished, dataThread, &QThread::deleteLater);
// 创建采集数据的对象并移动到线程中
dataWorker = new DataWorker();
dataWorker->moveToThread(dataThread);
// 开始采集数据
connect(dataThread, &QThread::started, dataWorker, &DataWorker::start);
// 停止采集数据
connect(this, &MainWindow::stopDataCollectionSignal, dataWorker, &DataWorker::stop);
// 存储数据到数据库中
connect(dataWorker, &DataWorker::dataReady, this, [=](int channel, int sensor, double value) {
QSqlQuery query;
query.prepare("INSERT INTO SensorData (channel, sensor, value) VALUES (:channel, :sensor, :value)");
query.bindValue(":channel", channel);
query.bindValue(":sensor", sensor);
query.bindValue(":value", value);
query.exec();
});
// 更新曲线图
connect(dataWorker, &DataWorker::dataReady, this, &MainWindow::updateChart);
}
void MainWindow::stopDataCollection()
{
// 停止采集数据
emit stopDataCollectionSignal();
if (dataThread->isRunning()) {
dataThread->quit();
dataThread->wait();
}
}
void MainWindow::updateChart()
{
// 清空曲线图
chart->removeAllSeries();
axisX->setRange(0, QDateTime::currentMSecsSinceEpoch());
axisY->setRange(-10, 10);
// 从数据库中取出数据
QSqlQuery query;
query.exec("SELECT * FROM SensorData");
// 遍历数据并添加到曲线图中
while (query.next()) {
int channel = query.value("channel").toInt();
int sensor = query.value("sensor").toInt();
double value = query.value("value").toDouble();
QDateTime timestamp = query.value("timestamp").toDateTime();
// 只添加选择的通道和传感器的数据
if (channel == selectedChannel && sensor == selectedSensor) {
QLineSeries *series = new QLineSeries();
series->setName(QString("%1-%2").arg(channel).arg(sensor));
series->append(timestamp.toMSecsSinceEpoch(), value);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
}
}
}
DataWorker::DataWorker(QObject *parent) : QObject(parent)
{
// 初始化随机数生成器
qsrand(QTime::currentTime().msec());
}
void DataWorker::start()
{
// 模拟采集数据,并发射dataReady信号
while (true) {
int channel = qrand() % 2 + 1;
int sensor = qrand() % 2 + 1;
double value = (qrand() % 21 - 10) / 10.0;
emit dataReady(channel, sensor, value);
QThread::usleep(100); // 模拟采集数据的时间
}
}
void DataWorker::stop()
{
// 停止采集数据
QThread::currentThread()->exit();
}
```
5. “学习打卡”桌面管理器- **核心功能**: 1. **日程录入**:学生可创建打卡记录,如“背单词30分钟”、“阅读15页”等。 2. **打卡提醒**:到指定时间或日期后,程序弹出提示窗口。 3. **统计分析**:饼图/柱状图展示各类打卡完成率或时间分配。 4. **历史记录**:查看过去的打卡情况,便于回顾和调整计划。 - **关键知识点**: - **Qt Charts**:使用QChart绘制统计图表。 - **定时器/QTimer**:周期性检查是否到达打卡时间。 - **数据库**:存储打卡记录、时间、完成度等信息。 - **用户交互**:QMessageBox提示或系统托盘提醒(QSystemTrayIcon)。
### 使用Qt开发学习打卡桌面管理器
#### 应用概述
要开发一个具备日程录入、打卡提醒、统计分析和历史记录功能的学习打卡桌面管理器,可以充分利用 Qt 提供的强大工具集。其中,`Qt Charts` 可用于绘制统计数据的图表,而 `QTimer` 则可用于实现定时提醒功能。此外,还需要结合 SQLite 数据库来存储用户的打卡记录和其他相关信息。
---
#### 技术栈与核心模块
以下是该应用的主要技术构成及其作用:
1. **UI 设计**:
使用 Qt Designer 或纯代码方式设计用户界面,包括输入框、按钮、表格视图以及图表区域。
2. **数据存储**:
基于 SQLite 创建本地数据库表,用于保存用户的历史打卡记录、日程安排等内容[^4]。
3. **定时提醒**:
使用 `QTimer` 实现定期触发事件的功能,比如每天固定时间发送打卡提醒通知[^1]。
4. **数据分析与可视化**:
运用 `Qt Charts` 绘制柱状图、折线图等形式展现用户的学习进度或习惯养成情况[^3]。
5. **用户交互逻辑**:
编写业务逻辑处理程序响应用户的操作请求,例如新增任务条目、修改已有计划或者查询某段时间内的完成状况等动作。
---
#### 开发流程详解
##### 1. 初始化项目环境
安装必要的开发包,并设置好工程文件 `.pro` 中的相关配置项:
```plaintext
QT += core gui charts sql widgets
CONFIG += c++17
SOURCES += main.cpp \
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
```
##### 2. 构建 UI 界面布局
定义窗口主要组成部分如下所示:
- 日历控件 (`QCalendarWidget`):方便选取日期范围;
- 输入编辑区 (`QLineEdit`, `QTextEdit`) :填写待办事项描述信息;
- 表格列表 (`QTableView`) : 展示已有的活动清单;
- 图形展示区 (`QChartView`) :呈现趋势变化曲线或其他形式的结果概览;
##### 3. 配置数据库连接
建立与 SQLite 的链接关系以便持久化储存各项资料:
```cpp
#include <QSqlDatabase>
#include <QSqlQuery>
bool createConnection() {
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("learning_tracker.db");
if (!db.open()) {
qDebug() << "Error: connection with database failed";
return false;
} else {
qDebug() << "Database: connection ok";
QString queryStr = "CREATE TABLE IF NOT EXISTS records (id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT, task TEXT)";
QSqlQuery query;
if(!query.exec(queryStr)){
qDebug()<<"Failed to create table.";
return false;
}
}
return true;
}
```
##### 4. 设置定时机制
借助 `QTimer` 对象每隔一段时间执行一次回调方法以检查是否到了预定时刻发出提示音效或是弹窗警告消息:
```cpp
void MainWindow::setupReminder(QTime time){
QTimer *timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(checkForReminders()));
QTime currentTime = QTime::currentTime();
int secondsUntilTrigger = time.secsTo(currentTime);
timer->start(secondsUntilTrigger*1000); // Convert from secs to ms.
}
// Slot function that gets called when the timer times out.
void MainWindow::checkForReminders(){
// Logic here...
}
```
##### 5. 整合图表显示
调用 `QtCharts` API 来加载所需的数据集合并渲染成直观易懂的形式供使用者参考比较不同维度的表现差异:
```cpp
#include <QtCharts/QLineSeries>
#include <QtCharts/QValueAxis>
#include <QtCharts/QChartView>
void MainWindow::updateStatisticsChart(const QVector<QPair<QString,int>> &dataPoints){
auto series = new QtCharts::QLineSeries();
foreach(auto point,dataPoints){
series->append(point.first.toDouble(),point.second);
}
chart()->removeAllSeries(); // Clear previous data before adding new one.
chart()->addSeries(series);
chart()->createDefaultAxes();
chart()->axisX()->setRange(0, dataPoints.count()-1);
chart()->axisY()->applyNiceNumbers();
}
```
---
#### 注意事项
- 性能考量下应避免一次性载入过多无关联性的冗余资讯影响整体运行效率[^1]。
- 跨平台移植过程中需注意各操作系统间可能存在细微差别之处做适当适配调整[^4]。
---
阅读全文
相关推荐








