【QT/C++】Qt定时器QTimer类的实现方法详解(超详细)

【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定时器知识点:

  1. QTimer类的使用

    • 基本定时器操作(启动、停止)
    • 单次触发和重复触发模式
    • 时间间隔设置
  2. 定时器信号与槽

    • timeout()信号的处理
    • 不同连接方式的使用
  3. 多种定时器应用场景

    • 简单定时触发
    • 计数器实现
    • 闹钟功能
    • 进度条更新
    • 事件日志记录
  4. 低级定时器

    • startTimer()和timerEvent()的使用
    • 多个定时器的管理
  5. 综合应用技巧

    • 定时器状态管理
    • 用户界面与定时任务的协调
    • 时间计算和转换
    • 错误处理和边界情况处理
相关推荐
MeowKnight9582 小时前
【Qt】Qt实践记录3——UDP通信
笔记·qt
REDcker2 小时前
前端打包工具 - Rollup 打包工具笔记
前端·笔记
研究司马懿2 小时前
【ETCD】ETCD常用命令
网络·数据库·云原生·oracle·自动化·运维开发·etcd
WBluuue2 小时前
数据结构与算法:树上倍增与LCA
数据结构·c++·算法
lsx2024062 小时前
MySQL WHERE 子句详解
开发语言
Tony Bai2 小时前
【Go模块构建与依赖管理】09 企业级实践:私有仓库与私有 Proxy
开发语言·后端·golang
lkbhua莱克瓦242 小时前
Java基础——集合进阶用到的数据结构知识点1
java·数据结构·笔记·github
Lucky小小吴2 小时前
开源项目5——Go版本快速管理工具
开发语言·golang·开源
Mr.Jessy2 小时前
Web APIs 学习第五天:日期对象与DOM节点
开发语言·前端·javascript·学习·html