【QT/C++】Qt定时器QTimer类的实现方法详解(超详细)
- 本文主要详细说明Qt中的定时器QTimer类的相关原理和实际应用。
(关注不迷路哈!!!)
文章目录
- 【QT/C++】Qt定时器QTimer类的实现方法详解(超详细)
-
- [1. 定时器基础概念](#1. 定时器基础概念)
- [2. Qt定时器类型](#2. Qt定时器类型)
-
- [2.1 基于事件的定时器(低级定时器)](#2.1 基于事件的定时器(低级定时器))
- [2.2 QTimer类(高级定时器)](#2.2 QTimer类(高级定时器))
- [3. QTimer详细用法](#3. QTimer详细用法)
-
- [3.1 基本操作](#3.1 基本操作)
- [3.2 信号与槽连接](#3.2 信号与槽连接)
- [4. 综合示例:多功能定时器应用](#4. 综合示例:多功能定时器应用)
-
- [4.1 头文件(timerapp.h)](#4.1 头文件(timerapp.h))
- [4.2 实现文件(timerapp.cpp)](#4.2 实现文件(timerapp.cpp))
- [4.3 主函数(main.cpp)](#4.3 主函数(main.cpp))
- [4.4 项目文件(timerapp.pro)](#4.4 项目文件(timerapp.pro))
- 总结
1. 定时器基础概念
Qt提供了多种定时器机制,用于在指定的时间间隔执行任务。定时器是GUI应用程序中常用的功能,可以用于更新界面、执行周期性任务等。
Qt提供了两种定时器机制
- 高级定时器 - 使用
QTimer类(推荐) - 低级定时器 - 使用
startTimer()和timerEvent()
使用场景对比
| 特性 | QTimer | 低级定时器 |
|---|---|---|
| 易用性 | 简单易用 | 较复杂 |
| 灵活性 | 高 | 中等 |
| 多定时器管理 | 自动管理 | 需手动管理 |
| 推荐程度 | 强烈推荐 | 特殊情况使用 |
2. Qt定时器类型
2.1 基于事件的定时器(低级定时器)
通过startTimer()和timerEvent()实现:
cpp
#include <QTimerEvent>
#include <QWidget>
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget()
{
// 启动定时器,间隔为1000毫秒
timerId = startTimer(1000);
}
protected:
// 重写定时器事件处理函数
void timerEvent(QTimerEvent *event) override
{
if (event->timerId() == timerId)
{
// 定时器触发时执行的代码
// 例如更新界面或执行其他任务
}
}
private:
int timerId; // 定时器ID
};
2.2 QTimer类(高级定时器)
QTimer是更常用和灵活的定时器类:
cpp
#include <QObject>
#include <QTimer>
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject()
{
timer = new QTimer(this);
// 连接超时信号
connect(timer, &QTimer::timeout, this, &MyObject::onTimeout);
}
void startTimer()
{
timer->start(1000); // 启动定时器,间隔1000毫秒
}
void stopTimer()
{
timer->stop(); // 停止定时器
}
private slots:
void onTimeout()
{
// 定时器超时时执行的代码
}
private:
QTimer *timer;
};
3. QTimer详细用法
3.1 基本操作
cpp
#include <QTimer>
// 创建定时器
QTimer *timer = new QTimer(parent);
// 启动定时器
timer->start(1000); // 1秒间隔
// 停止定时器
timer->stop();
// 设置单次触发
timer->setSingleShot(true);
// 检查定时器状态
if (timer->isActive())
{
// 定时器正在运行
}
3.2 信号与槽连接
cpp
// 方式1:传统连接方式
connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
// 方式2:现代连接方式(Qt5及以上)
connect(timer, &QTimer::timeout, this, &MyClass::onTimeout);
// 方式3:Lambda表达式
connect(timer, &QTimer::timeout, [=]() {
// 处理定时器超时
});
4. 综合示例:多功能定时器应用
以下是一个综合示例,展示定时器的各种用法:
4.1 头文件(timerapp.h)
cpp
#ifndef TIMERAPP_H
#define TIMERAPP_H
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMainWindow>
#include <QProgressBar>
#include <QPushButton>
#include <QSpinBox>
#include <QTabWidget>
#include <QTextEdit>
#include <QTime>
#include <QTimer>
#include <QVBoxLayout>
class TimerApp : public QMainWindow
{
Q_OBJECT
public:
TimerApp(QWidget *parent = nullptr);
~TimerApp();
private slots:
// 基础定时器槽函数
void startBasicTimer();
void stopBasicTimer();
void onBasicTimerTimeout();
// 计数器定时器槽函数
void startCounterTimer();
void stopCounterTimer();
void onCounterTimeout();
// 闹钟定时器槽函数
void setAlarm();
void onAlarmTimeout();
// 进度条定时器槽函数
void startProgressTimer();
void stopProgressTimer();
void onProgressTimeout();
// 事件定时器槽函数
void onEventTimerTimeout();
private:
void setupUI();
void updateClock();
// 基础定时器相关组件
QTimer *m_basicTimer;
QLabel *m_basicTimerLabel;
QPushButton *m_startBasicButton;
QPushButton *m_stopBasicButton;
QSpinBox *m_basicIntervalSpinBox;
// 计数器定时器相关组件
QTimer *m_counterTimer;
QLabel *m_counterLabel;
QPushButton *m_startCounterButton;
QPushButton *m_stopCounterButton;
QSpinBox *m_counterIntervalSpinBox;
int m_counterValue;
// 闹钟定时器相关组件
QTimer *m_alarmTimer;
QPushButton *m_setAlarmButton;
QSpinBox *m_alarmHourSpinBox;
QSpinBox *m_alarmMinuteSpinBox;
QSpinBox *m_alarmSecondSpinBox;
QLabel *m_alarmStatusLabel;
bool m_alarmSet;
// 进度条定时器相关组件
QTimer *m_progressTimer;
QProgressBar *m_progressBar;
QPushButton *m_startProgressButton;
QPushButton *m_stopProgressButton;
QLabel *m_progressLabel;
int m_progressValue;
// 时钟显示
QLabel *m_clockLabel;
QTimer *m_clockTimer;
// 事件定时器相关组件
QTimer *m_eventTimer;
QTextEdit *m_eventLog;
QSpinBox *m_eventIntervalSpinBox;
QPushButton *m_startEventButton;
QPushButton *m_stopEventButton;
QCheckBox *m_singleShotCheckBox;
int m_eventCount;
// 事件定时器(低级)
int m_eventTimerId;
int m_eventTimerInterval;
};
#endif // TIMERAPP_H
4.2 实现文件(timerapp.cpp)
cpp
#include <QApplication>
#include <QDateTime>
#include <QGroupBox>
#include <QMessageBox>
#include "timerapp.h"
TimerApp::TimerApp(QWidget *parent)
: QMainWindow(parent)
, m_counterValue(0)
, m_progressValue(0)
, m_alarmSet(false)
, m_eventCount(0)
, m_eventTimerId(0)
, m_eventTimerInterval(1000)
{
setupUI();
// 初始化定时器
m_basicTimer = new QTimer(this);
m_counterTimer = new QTimer(this);
m_alarmTimer = new QTimer(this);
m_progressTimer = new QTimer(this);
m_clockTimer = new QTimer(this);
m_eventTimer = new QTimer(this);
// 连接信号与槽
connect(m_basicTimer, &QTimer::timeout, this, &TimerApp::onBasicTimerTimeout);
connect(m_counterTimer, &QTimer::timeout, this, &TimerApp::onCounterTimeout);
connect(m_alarmTimer, &QTimer::timeout, this, &TimerApp::onAlarmTimeout);
connect(m_progressTimer, &QTimer::timeout, this, &TimerApp::onProgressTimeout);
connect(m_clockTimer, &QTimer::timeout, this, &TimerApp::updateClock);
connect(m_eventTimer, &QTimer::timeout, this, &TimerApp::onEventTimerTimeout);
// 启动时钟定时器
m_clockTimer->start(1000);
updateClock();
}
TimerApp::~TimerApp()
{
// 停止事件定时器
if (m_eventTimerId != 0)
{
killTimer(m_eventTimerId);
}
}
void TimerApp::setupUI()
{
QTabWidget *tabWidget = new QTabWidget;
// 基础定时器标签页
QWidget *basicWidget = new QWidget;
m_basicTimerLabel = new QLabel("定时器未启动");
m_basicTimerLabel->setAlignment(Qt::AlignCenter);
m_basicTimerLabel->setStyleSheet("font-size: 18px; color: blue;");
m_startBasicButton = new QPushButton("启动定时器");
m_stopBasicButton = new QPushButton("停止定时器");
m_basicIntervalSpinBox = new QSpinBox;
m_basicIntervalSpinBox->setRange(100, 10000);
m_basicIntervalSpinBox->setValue(1000);
m_basicIntervalSpinBox->setSuffix(" ms");
connect(m_startBasicButton, &QPushButton::clicked, this, &TimerApp::startBasicTimer);
connect(m_stopBasicButton, &QPushButton::clicked, this, &TimerApp::stopBasicTimer);
auto *basicControlLayout = new QHBoxLayout;
basicControlLayout->addWidget(new QLabel("间隔:"));
basicControlLayout->addWidget(m_basicIntervalSpinBox);
basicControlLayout->addWidget(m_startBasicButton);
basicControlLayout->addWidget(m_stopBasicButton);
auto *basicLayout = new QVBoxLayout;
basicLayout->addWidget(m_basicTimerLabel);
basicLayout->addLayout(basicControlLayout);
basicWidget->setLayout(basicLayout);
// 计数器定时器标签页
QWidget *counterWidget = new QWidget;
m_counterLabel = new QLabel("0");
m_counterLabel->setAlignment(Qt::AlignCenter);
m_counterLabel->setStyleSheet("font-size: 48px; color: green;");
m_startCounterButton = new QPushButton("启动计数器");
m_stopCounterButton = new QPushButton("停止计数器");
m_counterIntervalSpinBox = new QSpinBox;
m_counterIntervalSpinBox->setRange(10, 5000);
m_counterIntervalSpinBox->setValue(500);
m_counterIntervalSpinBox->setSuffix(" ms");
connect(m_startCounterButton, &QPushButton::clicked, this, &TimerApp::startCounterTimer);
connect(m_stopCounterButton, &QPushButton::clicked, this, &TimerApp::stopCounterTimer);
auto *counterControlLayout = new QHBoxLayout;
counterControlLayout->addWidget(new QLabel("间隔:"));
counterControlLayout->addWidget(m_counterIntervalSpinBox);
counterControlLayout->addWidget(m_startCounterButton);
counterControlLayout->addWidget(m_stopCounterButton);
auto *counterLayout = new QVBoxLayout;
counterLayout->addWidget(m_counterLabel);
counterLayout->addLayout(counterControlLayout);
counterWidget->setLayout(counterLayout);
// 闹钟定时器标签页
QWidget *alarmWidget = new QWidget;
m_setAlarmButton = new QPushButton("设置闹钟");
m_alarmHourSpinBox = new QSpinBox;
m_alarmMinuteSpinBox = new QSpinBox;
m_alarmSecondSpinBox = new QSpinBox;
m_alarmStatusLabel = new QLabel("闹钟未设置");
m_alarmHourSpinBox->setRange(0, 23);
m_alarmMinuteSpinBox->setRange(0, 59);
m_alarmSecondSpinBox->setRange(0, 59);
QTime currentTime = QTime::currentTime();
m_alarmHourSpinBox->setValue(currentTime.hour());
m_alarmMinuteSpinBox->setValue(currentTime.minute());
m_alarmSecondSpinBox->setValue(currentTime.second());
connect(m_setAlarmButton, &QPushButton::clicked, this, &TimerApp::setAlarm);
auto *alarmTimeLayout = new QHBoxLayout;
alarmTimeLayout->addWidget(new QLabel("时间:"));
alarmTimeLayout->addWidget(m_alarmHourSpinBox);
alarmTimeLayout->addWidget(new QLabel("时"));
alarmTimeLayout->addWidget(m_alarmMinuteSpinBox);
alarmTimeLayout->addWidget(new QLabel("分"));
alarmTimeLayout->addWidget(m_alarmSecondSpinBox);
alarmTimeLayout->addWidget(new QLabel("秒"));
alarmTimeLayout->addWidget(m_setAlarmButton);
auto *alarmLayout = new QVBoxLayout;
alarmLayout->addWidget(m_alarmStatusLabel);
alarmLayout->addLayout(alarmTimeLayout);
alarmLayout->addStretch();
alarmWidget->setLayout(alarmLayout);
// 进度条定时器标签页
QWidget *progressWidget = new QWidget;
m_progressBar = new QProgressBar;
m_progressLabel = new QLabel("进度: 0%");
m_progressLabel->setAlignment(Qt::AlignCenter);
m_startProgressButton = new QPushButton("开始进度");
m_stopProgressButton = new QPushButton("停止进度");
connect(m_startProgressButton, &QPushButton::clicked, this, &TimerApp::startProgressTimer);
connect(m_stopProgressButton, &QPushButton::clicked, this, &TimerApp::stopProgressTimer);
auto *progressButtonLayout = new QHBoxLayout;
progressButtonLayout->addWidget(m_startProgressButton);
progressButtonLayout->addWidget(m_stopProgressButton);
auto *progressLayout = new QVBoxLayout;
progressLayout->addWidget(m_progressLabel);
progressLayout->addWidget(m_progressBar);
progressLayout->addLayout(progressButtonLayout);
progressWidget->setLayout(progressLayout);
// 事件定时器标签页
QWidget *eventWidget = new QWidget;
m_eventLog = new QTextEdit;
m_eventLog->setReadOnly(true);
m_eventIntervalSpinBox = new QSpinBox;
m_eventIntervalSpinBox->setRange(100, 10000);
m_eventIntervalSpinBox->setValue(1000);
m_eventIntervalSpinBox->setSuffix(" ms");
m_singleShotCheckBox = new QCheckBox("单次触发");
m_startEventButton = new QPushButton("启动事件定时器");
m_stopEventButton = new QPushButton("停止事件定时器");
m_stopEventButton->setEnabled(false);
connect(m_startEventButton, &QPushButton::clicked, this, &TimerApp::startProgressTimer);
connect(m_stopEventButton, &QPushButton::clicked, this, &TimerApp::stopProgressTimer);
auto *eventControlLayout = new QHBoxLayout;
eventControlLayout->addWidget(new QLabel("间隔:"));
eventControlLayout->addWidget(m_eventIntervalSpinBox);
eventControlLayout->addWidget(m_singleShotCheckBox);
eventControlLayout->addWidget(m_startEventButton);
eventControlLayout->addWidget(m_stopEventButton);
auto *eventLayout = new QVBoxLayout;
eventLayout->addWidget(new QLabel("事件日志:"));
eventLayout->addWidget(m_eventLog);
eventLayout->addLayout(eventControlLayout);
eventWidget->setLayout(eventLayout);
// 时钟显示
QWidget *clockWidget = new QWidget;
m_clockLabel = new QLabel;
m_clockLabel->setAlignment(Qt::AlignCenter);
m_clockLabel->setStyleSheet("font-size: 36px; color: red;");
auto *clockLayout = new QVBoxLayout;
clockLayout->addWidget(m_clockLabel);
clockLayout->addStretch();
clockWidget->setLayout(clockLayout);
// 添加标签页
tabWidget->addTab(basicWidget, "基础定时器");
tabWidget->addTab(counterWidget, "计数器");
tabWidget->addTab(alarmWidget, "闹钟");
tabWidget->addTab(progressWidget, "进度条");
tabWidget->addTab(eventWidget, "事件定时器");
tabWidget->addTab(clockWidget, "时钟");
setCentralWidget(tabWidget);
setWindowTitle("Qt定时器综合示例");
resize(500, 400);
}
void TimerApp::startBasicTimer()
{
int interval = m_basicIntervalSpinBox->value();
m_basicTimer->start(interval);
m_basicTimerLabel->setText(QString("定时器已启动,间隔 %1 ms").arg(interval));
m_startBasicButton->setEnabled(false);
m_stopBasicButton->setEnabled(true);
}
void TimerApp::stopBasicTimer()
{
m_basicTimer->stop();
m_basicTimerLabel->setText("定时器已停止");
m_startBasicButton->setEnabled(true);
m_stopBasicButton->setEnabled(false);
}
void TimerApp::onBasicTimerTimeout()
{
m_basicTimerLabel->setText(QString("定时器触发: %1").arg(QDateTime::currentDateTime().toString("hh:mm:ss.zzz")));
}
void TimerApp::startCounterTimer()
{
m_counterValue = 0;
m_counterLabel->setText("0");
int interval = m_counterIntervalSpinBox->value();
m_counterTimer->start(interval);
m_startCounterButton->setEnabled(false);
m_stopCounterButton->setEnabled(true);
}
void TimerApp::stopCounterTimer()
{
m_counterTimer->stop();
m_startCounterButton->setEnabled(true);
m_stopCounterButton->setEnabled(false);
}
void TimerApp::onCounterTimeout()
{
m_counterValue++;
m_counterLabel->setText(QString::number(m_counterValue));
}
void TimerApp::setAlarm()
{
QTime alarmTime(m_alarmHourSpinBox->value(), m_alarmMinuteSpinBox->value(), m_alarmSecondSpinBox->value());
QTime currentTime = QTime::currentTime();
int msecsToAlarm = currentTime.msecsTo(alarmTime);
if (msecsToAlarm <= 0)
{
msecsToAlarm += 24 * 60 * 60 * 1000; // 加一天
}
m_alarmTimer->start(msecsToAlarm);
m_alarmSet = true;
m_alarmStatusLabel->setText(QString("闹钟已设置为 %1,将在 %2 后触发").arg(alarmTime.toString("hh:mm:ss")).arg(QTime(0, 0, 0).addMSecs(msecsToAlarm).toString("hh:mm:ss")));
m_setAlarmButton->setText("取消闹钟");
disconnect(m_setAlarmButton, &QPushButton::clicked, this, &TimerApp::setAlarm);
connect(m_setAlarmButton, &QPushButton::clicked, this, &TimerApp::stopProgressTimer);
}
void TimerApp::onAlarmTimeout()
{
m_alarmSet = false;
m_alarmStatusLabel->setText("闹钟响了!");
m_setAlarmButton->setText("设置闹钟");
QMessageBox::information(this, "闹钟", "时间到了!");
disconnect(m_setAlarmButton, &QPushButton::clicked, this, &TimerApp::stopProgressTimer);
connect(m_setAlarmButton, &QPushButton::clicked, this, &TimerApp::setAlarm);
}
void TimerApp::startProgressTimer()
{
m_progressValue = 0;
m_progressBar->setValue(0);
m_progressLabel->setText("进度: 0%");
m_progressTimer->start(100); // 每100ms更新一次
m_startProgressButton->setEnabled(false);
m_stopProgressButton->setEnabled(true);
}
void TimerApp::stopProgressTimer()
{
m_progressTimer->stop();
m_startProgressButton->setEnabled(true);
m_stopProgressButton->setEnabled(false);
// 如果是闹钟取消操作
if (sender() == m_setAlarmButton && m_alarmSet)
{
m_alarmTimer->stop();
m_alarmSet = false;
m_alarmStatusLabel->setText("闹钟已取消");
m_setAlarmButton->setText("设置闹钟");
}
}
void TimerApp::onProgressTimeout()
{
m_progressValue += 2;
if (m_progressValue > 100)
{
m_progressValue = 0;
}
m_progressBar->setValue(m_progressValue);
m_progressLabel->setText(QString("进度: %1%").arg(m_progressValue));
}
void TimerApp::updateClock()
{
m_clockLabel->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
}
void TimerApp::onEventTimerTimeout()
{
m_eventCount++;
m_eventLog->append(QString("[%1] 事件定时器触发 #%2").arg(QDateTime::currentDateTime().toString("hh:mm:ss.zzz")).arg(m_eventCount));
}
4.3 主函数(main.cpp)
cpp
#include <QApplication>
#include "timerapp.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
TimerApp window;
window.show();
return app.exec();
}
#include "main.moc"
4.4 项目文件(timerapp.pro)
pro
QT += core gui widgets
CONFIG += c++11
TARGET = TimerApp
TEMPLATE = app
SOURCES += \
main.cpp \
timerapp.cpp
HEADERS += \
timerapp.h
总结
这个综合示例演示了以下Qt定时器知识点:
-
QTimer类的使用:
- 基本定时器操作(启动、停止)
- 单次触发和重复触发模式
- 时间间隔设置
-
定时器信号与槽:
- timeout()信号的处理
- 不同连接方式的使用
-
多种定时器应用场景:
- 简单定时触发
- 计数器实现
- 闹钟功能
- 进度条更新
- 事件日志记录
-
低级定时器:
- startTimer()和timerEvent()的使用
- 多个定时器的管理
-
综合应用技巧:
- 定时器状态管理
- 用户界面与定时任务的协调
- 时间计算和转换
- 错误处理和边界情况处理