精华内容
下载资源
问答
  • Qtimer
    千次阅读
    2021-10-25 17:12:45

    目录

    一、QTimer类使用

    1、使用start开启 重复循环定时任务

    2、单次延迟任务

    3、超时为0的任务

    4、一个综合点的例子


    The QTimer class provides repetitive and single-shot timers. This class provide a high level programming interface for timers.

    QTimer类提供重复和单次的定时器。

    一、QTimer类使用


    1、使用start开启 重复循环定时任务

    First create a QTimer and then connect the timeout() signal to the appropriate slots. Call start() on the timer. From then on the timer will emit the timeout() signal at constant intervals.

    首先创建一个 QTimer,然后将 timeout() 信号连接到适当的槽。 在计时器上调用 start()。 从那时起,计时器将以恒定的时间间隔发出 timeout() 信号。

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(1000);

    每一秒执行一次update()

    In the example above, the update() slot is called once every second.

    2、单次延迟任务

    
    void QTimer::singleShot	(	int 	msec,
    const QObject * 	receiver,
    const QString & 	slotMethod 
    )	
    QTimer::singleShot(200, this, SLOT(updateCaption()));

    又如:

    #include <QApplication>
    #include <QTimer>
     
    int main(int argc, char *argv[]) {
       QApplication app(argc, argv);
       QTimer::singleShot(600000, &app, SLOT(quit()));
     
       ...
     
       return app.exec();
    }

    3、超时为0的任务

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(processOneThing()));
    timer->start();

    超时为 0 的 QTimer 将在处理完窗口系统事件队列中的所有事件后立即超时。 这可以用来做繁重的工作,同时提供一个活泼的用户界面:

    4、一个综合点的例子

    	recordingTimerDisplay = new QTimer(this);
    	QObject::connect(recordingTimerDisplay, SIGNAL(timeout()), this,
    		SLOT(UpdateRecordTimerDisplay()));
    	recordingTimerDisplay->start(1000);
    
    
    
    
    
    	if (recordingTimerDisplay->isActive())
    		recordingTimerDisplay->stop();

    	recordingTimer = new QTimer(this);
    
    	int total = (((hours * 3600) +
    			(minutes * 60)) +
    			seconds) * 1000;
    
    	if (total == 0)
    		total = 1000;
    
    	recordingTimer->setInterval(total);
    	recordingTimer->setSingleShot(true);
    
    
    
    	QObject::connect(recordingTimer, SIGNAL(timeout()),
    		SLOT(EventStopRecording()));
    
    
    	recordingTimer->start();
    
    
    	if (recordingTimer->isActive())
    		recordingTimer->stop();
    
    
    
    
    
    
    

    参考资料:CopperSpice API : QTimer Class Reference

    更多相关内容
  • Qt教程-QTimer的精度测试,用自绘的曲线控件,对比了QTimer和windows多媒体计时器的精度
  • 主要为大家详细介绍了QTimer与QTime实现电子时钟,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • QTimer在子线程里执行例子,代码简单,调试方便 vs2008
  • Qt基础开发之基础开发之Qt多线程类多线程类QThread与与Qt定时器类定时器类QTimer的详的详细方法与实例细方法与实例Qt多线程多线程我们之前的程序都是单线程运行,接下来我们开始引入多线程。就相当于以前的一个人在...
  • QT实战,利用定时器QTimer实现图片的移动!主要是练习QT资源文件的添加及使用方法,及定时器方法和功能。
  • 如果在应用程序中周期性地进行某项操作,比如周期性的检测主机的cpu值,则需要用到QTimer定时器,QTimer类提供了重复和单次的定时器,要使用定时器,需要先创建一个QTimer实例,将其Timeout信号连接到槽函数,并调用...
  • 今天小编就为大家分享一篇python之当你发现QTimer不能用时的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 24_QTimer.rar

    2021-01-30 21:09:44
    24_QTimer.rar,24_QTimer,24_QTimer.pro,24_QTimer.pro.user,widget.ui,main.cpp,widget.cpp,widget.h
  • QTimer使用,Pyqt界面制作和打包pyinstaller -F GOODOK --noconsole pyinstaller specfile
  • QTimer.rar_qtimer

    2022-07-15 05:20:58
    介绍QT中的QTimer的使用,并举例说明
  • Qt组件QTimer使用方法.rar,QTimer.pro.user,QTimer.pro,Qt组件QTimer使用方法.png,main.cpp,mainwindow.ui,mainwindow.cpp,mainwindow.h
  • QTimer

    2019-10-07 08:37:20
    目录 简述 详细说明 精度 替代QTimer 成员函数 信号 示例 简述 QTimer类提供了重复和单次触发信号的定时器。 QTimer类为定时器提供了一个高级别的编程接口。很容易使用:首先,...

    简述

    QTimer类提供了重复和单次触发信号的定时器。

    QTimer类为定时器提供了一个高级别的编程接口。很容易使用:首先,创建一个QTimer,连接timeout()信号到适当的槽函数 , 并调用start(),然后在恒定的时间间隔会发射timeout()信号。

    注意:当QTimer的父对象被销毁时,它也会被自动销毁。

    详细说明

    1秒(1000毫秒)更新一次:

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(1000);
    
    //Widget::Widget(QWidget *parent)
    //    : QWidget(parent)
    //{
    //    QTimer *timer = new QTimer(this);
    //    QObject::connect(timer,&QTimer::timeout,this,[=](){
    //        qDebug() <<"定时器触发了";
    //    });
    //    timer->start();// 缺省就是0毫妙
    //}
    
    

    start()之后,每秒都会调用update()可以通过设置setSingleShot(true)来让定时器只执行一次。也可以使用静态函数QTimer::singleShot():

    QTimer::singleShot(200, this, SLOT(updateCaption()));

    在多线程程序中,可以在一个有事件循环的任何线程中使用QTimer。使用QThread::exec(),从非GUI线程启动一个事件循环。
    Qt使用定时器的线程关联,以确定哪个线程会发出timeout()信号。正因为如此,你必须在它的线程中启动和停止定时器,不可能从另一个线程启动定时器。

    作为一个特例,一旦窗口系统事件队列中的所有事件都已经被处理完,一个定时为0的QTimer就会到时间了。当需要提供流畅的用户界面时,可以用这来做比较繁重的工作。

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()),  this, SLOT(processOneThing()));
    timer->start();

    这时,processOneThing()将会被重复调用并且应该很快返回(通常在处理一个数据项之后),这样Qt可以把事件传送给窗口部件,并且一旦它完成这个工作就停止这个定时器。这是在图形用户界面应用程序中实现繁重的工作的一个典型方法,现在多线程可以在越来越多的平台上使用,我们希望0-毫秒QTimer对象最终被线程替代。 其实这样是不对的,能有代替多线程的方案尽量不用多线程。

    精度

    定时器的精度取决于底层操作系统和硬件。绝大多数平台支持精度为1毫秒,尽管定时器的准确性在许多现实世界的情况下和这不相符。

    准确性也取决于定时器类型(Qt::TimerType)。对于Qt::PreciseTimer来说,QTimer将试图保持精确度在1毫秒。精确的定时器也从来不会比预计的还要早超时。

    对于Qt::CoarseTimer和Qt::VeryCoarseTimer类型,QTimer可能早于预期,在间隔之内被唤醒:Qt::CoarseTimer为间隔的5%,Qt::VeryCoarseTimer为500毫秒。

    枚举Qt::TimerType:

    常量描述
    Qt::PreciseTimer0精确的定时器,尽量保持毫秒精度。
    Qt::CoarseTimer1粗略的定时器,尽量保持精度在所需的时间间隔5%范围内。
    Qt::VeryCoarseTimer2很粗略的定时器,只保留完整的第二精度。

    在UNIX (包括: Linux、OS X、iOS)中,Qt将为Qt::PreciseTimer保持毫秒精度,对于Qt::CoarseTimer,间隔将调整到5%,使定时器与其他定时器匹配或在差不多在同一时间,目标是让大多数定时器在同一时间醒来,从而减少CPU唤醒和功耗。

    在Windows上,Qt将为Qt::PreciseTimer使用Windows的多媒体定时器工具(如果可用),为Qt::CoarseTimer和Qt::VeryCoarseTimer使用正常的Windows定时器。

    所有平台上,Qt::VeryCoarseTimer的间隔被四舍五入到最接近完整的第二位(例如:23500ms的时间间隔将被舍入到24000ms,20300ms舍入至20000)。

    替代QTimer

    • 另一个使用QTimer的方法:为你的对象调用QObject::startTimer(),在你的类中(必须继承QObject)重新实现QObject::timerEvent()事件处理器。缺点是timerEvent()不支持像单次触发定时器或信号那样的高级特性。

    • 另一个选择是QBasicTimer。它通常比使用QObject::startTimer() 直接。可以查看助手中Timers描述的三种方法。
      一些操作系统限制可能会限制定时器的数量,Qt会尽力在限制范围内工作。

    可参考:QBasicTimer、QTimerEvent、QObject::timerEvent()、Timers、Analog Clock Example、Wiggly Example。

    成员函数

    bool isActive() const
    如果定时器正在运行,返回true,否则返回false。
    
    int remainingTime() const
    返回定时器的剩余时间(毫秒为单位),直到超时。
    
    如果定时器不活跃,返回值是-1。如果定时器过期,返回值为0。
    
    void setInterval(int msec)
    设置超时间隔(毫秒为单位)。
    
    默认值是0,这时,一旦窗口系统事件队列中的所有事件都已经被处理完,一个时间间隔为0的QTimer就会触发。
    
    void setSingleShot(bool singleShot)
    设置定时器是否为单次触发。
    
    单次触发定时器只触发一次,非单次的话,则每过一个时间间隔都会触发。
    
    void setTimerType(Qt::TimerType atype)
    设置定时器的准确性。默认值是Qt::CoarseTimer。
    
    int timerId() const
    如果定时器正在运行,返回定时器的ID,否则返回-1。
    
    void start(int msec)
    启动或重新启动一个超时时间间隔为毫秒的定时器。
    
    如果定时器正在运行,它将被停止和重新启动。如果singleShot为true,定时器将只激活一次。
    
    void start()
    同上,重载了start()。
    
    void stop()
    停止定时器。

    信号

    void timeout()
    定时器超时后,这个信号被发射。
    
    注意:这是一个私有的信号。它可以在信号连接使用,但不能由用户发出。

    示例

    下面,我们以QTimer为例,利用开始和停止按钮来操作一个进度条的更新。

    715664-20190929103724618-1623210544.png

    // .h
    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QProgressBar>
    #include <QTimer>
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent = 0);
        ~Widget();
    
    private:
        QProgressBar *m_progressbar;
        QTimer *m_timer;
    
    private slots:
        void updataProgressBar();
    };
    
    #endif // WIDGET_H
    
    
    //.cpp
    
    #include "widget.h"
    #include <QDebug>
    #include <QPushButton>
    #include <QHBoxLayout>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {
        QPushButton *btn_start =  new QPushButton(this);
        QPushButton *btn_stop = new QPushButton(this);
        m_progressbar = new QProgressBar(this);
        m_timer = new QTimer(this);
    
        QHBoxLayout *layout = new QHBoxLayout(this);
        layout->addWidget(m_progressbar);
        layout->addWidget(btn_start);
        layout->addWidget(btn_stop);
        setLayout(layout);
    
        btn_start->setText(tr("start"));
        btn_stop->setText(tr("stop"));
    
        m_progressbar->setOrientation(Qt::Horizontal);
        m_progressbar->setRange(0,100);
        m_progressbar->setValue(0);
        // 设置时间间隔
        m_timer->setInterval(1000);
        //singal slots
        connect(btn_start,&QPushButton::clicked,m_timer,static_cast<void(QTimer::*)()>(&QTimer::start));
        connect(btn_stop,&QPushButton::clicked,m_timer,&QTimer::stop);
        connect(m_timer,&QTimer::timeout,this,&Widget::updataProgressBar);
    
    }
    
    Widget::~Widget()
    {
    
    }
    
    void Widget::updataProgressBar()
    {
        // 获取当前进度值,+1
        int nCurrentValue = m_progressbar->value();
        ++nCurrentValue;
    
        if(nCurrentValue >=100){
            m_timer->stop();
        }
        // 设置新的进度值
        m_progressbar->setValue(nCurrentValue);
    
    }

    在槽函数updataProgressBar()中,首先通过m_progressbar->value()来获取当前进度值,然后加1,当进度大于等于100时停止定时器(再继续执行已经没任何意义了,因为进度已经达到了100,而且不停止还消耗资源),然后设置进度条的值。

    参考处 :https://blog.csdn.net/liang19890820/article/details/51789796

    转载于:https://www.cnblogs.com/__tudou__/p/11606409.html

    展开全文
  • 多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理。 用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条...
  • 实现功能:有时候做项目需要用到滚动字幕的效果,其实实现很简单,只需要使用一个定时器QTimer和QLabel就可以达到效果啦。
  • Qt定时器QTimer使用教程与代码演示

    千次阅读 2021-11-20 17:02:46
    Qt提供了定时器类QTimer, 在使用时需要包含头文件 #include <QTimer> QTimer类方法介绍: void start(int msec); 开启定时器,定时间隔的msec毫秒 void stop(); 结束定时 QTimer信号: void timeout...

    Qt提供了定时器类QTimer, 在使用时需要包含头文件

    #include <QTimer>
    

    QTimer类方法介绍:

    • void start(int msec); 开启定时器,定时间隔的msec毫秒
    • void stop(); 结束定时

    QTimer信号:

    • void timeout(QPrivateSignal); 在链接定时器时,需要绑定该信号

    QTimer的基本使用

    下面介绍如何使用Qt定时器实现一个秒表。
    新建一个Qt MainWindow项目,界面如下:
    在这里插入图片描述
    时间的显示用的LCD控件 QLCDNumber

    运行效果
    在这里插入图片描述

    MainWindow 头文件代码:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QTimer>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        void on_btnStart_clicked();
        void on_btnStop_clicked();
        void on_btnContinue_clicked();
        void on_timer();
    
    private:
        Ui::MainWindow *ui;
    
        QTimer *m_pTimer;
        int     m_counts = 0;   //时间计数
    };
    #endif // MAINWINDOW_H
    

    在头文件定义了定时器对象指针m_pTimer,毫秒计数m_counts

    MainWindow cpp代码

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
    	//LCD控件,需要先设置显示的数字个数,再显示数字,不然显示不全
        ui->lcdNumber->setDigitCount(9);
        ui->lcdNumber->display("00:00:000");
    
    	//new QTimer, 设置定时器类型
        m_pTimer = new QTimer(this);
        m_pTimer->setTimerType(Qt::PreciseTimer);
    
    	//链接定时器信号timeout,当调用start时,触发槽函数on_timer
        connect(m_pTimer, &QTimer::timeout, this, &MainWindow::on_timer);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    //开始计时
    void MainWindow::on_btnStart_clicked()
    {
        m_pTimer->start(1);   //开启定时器,频率为1ms
        m_counts = 0;
    }
    
    //暂停计时
    void MainWindow::on_btnStop_clicked()
    {
        m_pTimer->stop();
    }
    
    //继续计时
    void MainWindow::on_btnContinue_clicked()
    {
        m_pTimer->start(1);
    }
    
    void MainWindow::on_timer()
    {
        m_counts++;
        char buf[64];
    
        if(m_counts < 1000)  //1秒以内
        {
            sprintf(buf, "00:00:%03d", m_counts);
        }
        else if(m_counts > 1000 && m_counts < 60 * 1000) //一分钟以内
        {
            int seconds = m_counts / 1000;
            int ms = m_counts - seconds * 1000;
            sprintf(buf, "00:%02d:%03d", seconds, ms);
        }
        else
        {
            int mins = m_counts / (60 * 1000);
            int seconds = (m_counts - mins * 60 * 1000) / 1000;
            int ms = m_counts - mins * 60 * 1000 - seconds * 1000;
            sprintf(buf, "%02d:%02d:%03d", mins, seconds, ms);
        }
    
        ui->lcdNumber->display(buf);
    }
    

    需要注意的是,QTimer可以设置类型,也就是调用setTimerType进行设置,QTimer声明的定时器类型如下:

    enum TimerType {
            PreciseTimer,
            CoarseTimer,
            VeryCoarseTimer
        };
    

    这三种什么意思呢,Qt助手的解释如下:

    • Qt::PreciseTimer 精确的计时器试图保持毫秒的精确度
    • Qt::CoarseTimer 粗计时器试图将精度保持在所需间隔的5%以内
    • Qt::VeryCoarseTimer 非常粗糙的计时器只能保持完全的秒精度

    在new QTimer时,可以根据需求设置定时器精度。

    在UNIX(包括Linux, macOS和iOS)上,Qt将保持毫秒精度的Qt::PreciseTimer。对于Qt::CoarseTimer,间隔将被调整至5%,以使计时器与其他预期在或大约在同一时间触发的计时器对齐。目标是让大多数计时器在同一时间唤醒,从而减少CPU唤醒和功耗。

    在Windows上,Qt将使用Windows的多媒体定时器工具(如果可用)用于Qt::PreciseTimer和普通的Windows定时器用于Qt::CoarseTimer和Qt::VeryCoarseTimer。

    在所有平台上,Qt::VeryCoarseTimer的间隔被舍入到最近的满秒(例如,23500ms的间隔将被舍入到24000ms, 20300ms将被舍入到20000ms)。

    QTimer::singleShot使用说明

    QTimer除了周期性的执行某种操作,还可以单次执行,QTimer的静态函数singleShot就是为了实现这种单次操作功能,singleShot在一个给定时间间隔 msec(毫秒) 之后调用一个槽,例如下面的代码:

    void MainWindow::on_pushButton_clicked()
    {
        QTimer::singleShot(3000,this,[=]{
            //想要执行的代码
            qDebug() << "hello world" ;
        });
    }
    

    在3000ms后,将打印hello world, 上面是用的lambdab函数,也可以用类成员函数来写,代码如下:
    头文件,在头文件定义成员函数do_single,给QTimer::singleShot做槽函数

    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    	//定义成员函数,给QTimer::singleShot做槽函数
        void do_single();
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::MainWindow *ui;
    };
    

    cpp文件

    void MainWindow::on_pushButton_clicked()
    {
    //    QTimer::singleShot(3000,this,[=]{
    //        //想要执行的代码
    //        qDebug() << "hello world" ;
    //    });
    
        QTimer::singleShot(3000, this, &MainWindow::do_single);
    }
    
    void MainWindow::do_single()
    {
        qDebug() << "hello world" ;
    }
    

    注意singleShot它只会触发一次,发出一次信号,然后来执行槽函数。

    展开全文
  • 例子代码适用于, 主线程提供gui相关功能,次线程周期触发调用,请求socket服务相关。 在参考了不少国内外代码,实现此功能。 代码在qt5.3 vs2010下环境测试通过。 服务器直接用 ... 希望对大家有所帮助。
  • QtTimer_utils 很少有实用程序函数可让QtCore.QTimer以有限方式使用计时器。 该示例旨在作为FreeCAD宏在我面对那里的问题的同时进行开发。
  • qt定时器Qtimer

    2013-10-30 14:59:29
    分windows linux中Timerlinux在linux中解压用qt打开另一个在windows中
  • Qt学习之定时器QTimer类编程

    千次阅读 2022-03-17 09:28:34
    在进行控制系统上位机编程时,我们经常需要用到定时器,在定时服务函数中执行控制动作或者显示数据等,编程时候使用到的类是QTimer类,我们要创建两个定时器,第一个定时器是在对话框的界面线程中创建的,他的定时...

    1 引言

    在进行控制系统上位机编程时,我们经常需要用到定时器,在定时服务函数中执行控制动作或者显示数据等,编程时候使用到的类是QTimer类,我们要创建两个定时器,第一个定时器是在对话框的界面线程中创建的,他的定时事件在主循环中进行,而第二个定时器是在一个子线程中创建的,它的定时事件在子线程中循环,不受主线程其他事件的影响,我认为如果程序对于定时精度要求高的话,最好采用第二种设计方法,如果是诸如显示数据之类的对定时精度要求不高的动作,则可以采用第一种设计方法,更加省时省力。

    2 准备工作

    定时器需要用到QTimer类,此外,为了创建和管理子线程,我们自己编写一个线程类MyThread,它继承于QThread类,对话框类的头文件如下:

    #include <QDialog>
    #include <QTimer>
    #include "mythread.h"
    

    线程类的头文件如下,这里增加QDialog类和QtWidgets类主要是为了在子线程中控制窗口控件。

    #include <QThread>
    #include <QDialog>
    #include <QTimer>
    #include <QtWidgets>
    

    3 设计界面

    在这里插入图片描述左边的编辑框用于设置定时间隔,单位是ms,我们定义了一个Int型变量,每进入一次定时事件,变量加1,并将变量值显示在右边的编辑框中。

    4 定时方法

    有三种设计方法:
    第一种是使用startTimer()函数,输入参数为定时时间,返回值为ID值,用于区别多个定时器,需要重写定时器timerEvent(),在重写函数中判断定时器ID并执行不同的操作。
    第二种是创建QTimer对象,用connect函数将该对象的timeout()函数与自定义的槽函数连接,这种方法就是本文用到的方法。
    第三中是QBasicTimer类,我没有详细了解过。

    5 定时精度

    定时精度主要依靠平台自身的精度,用setTimerType()函数设置,输入的参数有以下几个选择:

    • Qt::PreciseTimer:QTimer 将尝试将精度保持在 1 毫秒。
    • Qt::CoarseTimer:QTimer 可能比预期更早唤醒,提前量为定时间隔的5%
    • Qt::VeryCoarseTimer :QTimer 可能比预期更早唤醒,提前量为500ms

    6 程序设计

    (1)构造函数
    在构造函数中初始化计数变量为0,并将指针变量赋为空指针

        Mytimer=NULL;
        Timer1Count=0;
        mythread=NULL;
    

    (2)定时器1的设计
    我们设计点击打开定时器1按钮的槽函数,在函数中首先判断按钮当前的标题如果是“打开定时器”,则执行打开定时器的操作,包括,新建一个QTimer类的对象,使用setTimerType函数设置定时器的精度,将timeout()信号和我们自己编写的槽函数MyTimerFunc()连接起来,那么当定时时间到了,系统就会发出timerout()信号,从而调用我们的MyTimerFunc(),最后我们使用start()函数开启定时器,将编辑框中的内容转化为Int型传入,start函数需要传入的参数是时间间隔(Int型变量),
    如果按钮当前的标题如果不是“打开定时器”,则执行关闭定时器的相关操作,如果Mytimer指针变量不为NULL,使用stop函数停止定时器,用deleteLater()释放指针,这个函数的效果类似于delete Mytimer,官方推荐当我们需要释放一个QObject对象时候,使用deleteLater()而不是delete ,因为前者是线程安全的,最后,把指针重新赋值为空指针,清空编辑框。

    void MyDialog::on_OpenTimer1Btn_clicked()
    {
        if(ui->OpenTimer1Btn->text()==QString("打开定时器1"))
        {
            Mytimer=new QTimer(this);
            Mytimer->setTimerType(Qt::TimerType::PreciseTimer);
            connect(Mytimer,SIGNAL(timeout()),this,SLOT(MyTimerFunc()));
            Mytimer->start(ui->TimeInterval1Edt->text().toInt());
            ui->OpenTimer1Btn->setText(QString("关闭定时器1"));
        }
        else
        {
            if(Mytimer!=NULL)
            {
                Mytimer->stop();
                Mytimer->deleteLater();
                Mytimer=NULL;
                ui->TimeCount1Edt->clear();
                ui->OpenTimer1Btn->setText(QString("打开定时器1"));
            }
        }
    }
    

    (3)定时器1的事件函数

    我这里例子中的事件函数比较简单,仅仅在函数中对计数变量加1并显示,代码如下:

    void MyDialog::MyTimerFunc()
    {
        if(Timer1Count==10000)
            Timer1Count=0;
        else
            Timer1Count++;
        ui->TimeCount1Edt->setText(QString("%1").arg(Timer1Count));
    }
    

    (4)定时器2的设计
    定时器2的设计比较麻烦,我们先来看一看自己编写的线程类中的头文件

    class MyThread : public QThread
    {
        Q_OBJECT
    public:
        MyThread(int timeinterval);
        ~MyThread();
        QLineEdit* mythreadEdt;
        void SetUiEdt(QLineEdit* p) {mythreadEdt=p;}
    private:
        int MyTimerInterval;
        int MyCount;
    protected:
        void run();
    private slots:
        void MyTimerFunc();
    signals:
        void MySignalChangeEdt(const QString&);
    };
    

    根据线程的相关知识,我们在继承QThread的时候,必须重写基类的run()函数,函数中的内容就是我们需要在线程中执行的内容。那么我们在设计的过程中,打开和关闭定时器2的操作实际上是打开和关闭子线程的操作,在子线程的run()函数中创建定时器对象,并且在子线程的定时器事件函数执行计数值累加的操作。具体我们可以看到打开和关闭定时器2的代码如下:

    void MyDialog::on_OpenTimer2Btn_clicked()
    {
        if(ui->OpenTimer2Btn->text()==QString("打开定时器2"))
        {
            mythread=new MyThread(ui->TimeInterval2Edt->text().toInt());
            connect(mythread,&MyThread::finished,this,&MyDialog::closeMythread);
            mythread->SetUiEdt(ui->TimeCount2Edt);
            mythread->start();
            ui->OpenTimer2Btn->setText(QString("关闭定时器2"));
        }
        else
        {
            mythread->exit();
            ui->OpenTimer2Btn->setText(QString("打开定时器2"));
        }
    }
    

    这里我们为指针变量mythread创建一个MyThread对象,构造函数的参数是时间间隔,当然你可以设计别的方法将编辑框中的数据传递给线程对象,然后将线程对象的finished()信号,和我们自己定义的closeMythread函数连接起来,finished()信号是QThread类自带的一个信号,当run()函数执行完以后自动发出,这时候代表这个线程把它该做的事情都做完了,我们就可以利用deleteLater()函数释放掉指针,最后将mythread指针赋为空指针,防止它成为野指针。

    void MyDialog::closeMythread()
    {
        mythread->deleteLater();
        mythread=NULL;
    }
    

    SetUiEdt()函数的目的是将我们对话框上的用于显示计数变量的编辑框的指针传递给MyThread类,MyThread类有一个QLineEdit类型的指针变量接收,通过这种方式我们就可以在MyThread类的函数中操作对话框上的控件了。最后,我们使用start()函数开启线程。
    在关闭定时器2的操作中,我们使用exit()函数停止线程,这一点后边会详细说明,同时,因为线程结束会发出finish()信号,我们已经将这个信号和释放指针等操作连接起来了,所以这里就不用再写这些操作了。
    (4)子线程的设计
    在线程类的构造函数中,我们初始化编辑控件变量指针和相关参数,moveToThread(this)这句话的意思将在后面解释。

    MyThread::MyThread(int timeinterval)
    {
        MyTimerInterval=timeinterval;
        MyCount=0;
        mythreadEdt=NULL;
        moveToThread(this);
    }
    

    析构函数中,清空编辑框内容,并将指针设置为空指针

    MyThread::~MyThread()
    {
        if(mythreadEdt!=NULL)
        {
            mythreadEdt->clear();
            mythreadEdt=NULL;
        }
    };
    

    接下来我们看看线程函数中要执行的内容:

    void MyThread::run()
    {
        connect(this,SIGNAL(MySignalChangeEdt(const QString &)),
                           mythreadEdt,SLOT(setText(const QString &)));
        QTimer *MyThreadQtimer=new QTimer();
        MyThreadQtimer->setTimerType(Qt::TimerType::PreciseTimer);
        connect(MyThreadQtimer,SIGNAL(timeout()),this,SLOT(MyTimerFunc()));
        MyThreadQtimer->start(MyTimerInterval);
        exec();
        if(MyThreadQtimer!=NULL)
        {
            MyThreadQtimer->deleteLater();
            MyThreadQtimer=NULL;
        }
    }
    

    第一个connect中的MySignalChangeEdt是我们自己定义的信号,连接的槽函数是编辑框控件指针的setText函数,效果就是如果有MySignalChangeEdt信号产生,那么就会根据信号的参数设置GUI界面编辑框中显示的内容,用于显示计数值。
    接下来关于创建和设置定时器的内容上面已经说过,这里就不在重复说明了,紧接着我们调用 exec(),那么程序就会进入事件循环,在这里一直等待事件的发生,直到exit()函数被调用,exec()函数才会返回,执行下面释放QTimer对象的操作,然后退出线程,最后退出线程以后,线程对象就会自动发送finished()信号,发射过程用户是不可见的。
    定时器的事件处理函数如下,每次定时时间到了,计数变量加一,并且发送MySignalChangeEdt()信号用于在编辑框中显示。

    void MyThread::MyTimerFunc()
    {
        if(MyCount==10000)
            MyCount=0;
        else
            MyCount++;
        emit MySignalChangeEdt(QString("%1").arg(MyCount));
    }
    

    注意:
    以下内容参考自链接:QT 信号和槽在哪个线程执行问题
    在这里解释一下moveToThread(this)这句话的意思,我们知道run()函数是在新线程中运行的,那我们的MyTimerFunc()是在哪儿运行的呢?实际上这是由connect函数连接时的连接方式确定的,这里给出connect函数的三种连接方式说明

    • 自动连接(Auto Connection)

       这是默认设置
       如果信号在接收者所依附的线程内发射,则等同于直接连接
       如果发射信号的线程和接受者所依附的线程不同,则等同于队列连接
       也就是这说,只存在下面两种情况
      
    • 直接连接(Direct Connection)

       当信号发射时,槽函数将直接被调用。
       无论槽函数所属对象在哪个线程,槽函数都在发射信号的线程内执行。
      
    • 队列连接(Queued Connection)

       当控制权回到接受者所依附线程的事件循环时,槽函数被调用。
       槽函数在接收者所依附线程执行。
      

    对照我们程序中的语句connect(MyThreadQtimer,SIGNAL(timeout()),this,SLOT(MyTimerFunc()));发出信号的QTimer对象是在新线程内,接收槽函数是在MyThread类中定义的,而MyThread类的对象依附于主线程,所以属于队列连接,槽函数也就是MyTimerFunc()就会在主线程中执行,而这显然与我们想要的不符,我们想在新的线程内执行定时器服务程序以提高执行效率,因此由两种解决方法:
    1将connect函数的最后一个参数设置为直接连接,但这样子需要在槽函数增加线程同步的操作,非常麻烦。
    2.在线程派生类的构造函数中增加语句moveToThread(this),就是本文用到的,但这种方法不推荐

    推荐的一种方法如下:
    我们新建一个类,在这个类中只做一件事,就是执行我们的定时服务程序,关于这个类的声明如下所示:

    class MyObject:public QObject
    {
        Q_OBJECT
    public:
        int MyCount;
        MyObject();
        ~MyObject();
    signals:
        void MySignalChangeEdt(const QString&);
    public slots:
        void MyTimerFunc();
    };
    

    那么线程的run函数变为:

    void MyThread::run()
    {
        MyObject obj;
        connect(&obj,SIGNAL(MySignalChangeEdt(const QString &)),
                            mythreadEdt,SLOT(setText(const QString &)));
        QTimer *MyThreadQtimer=new QTimer();
        MyThreadQtimer->setTimerType(Qt::TimerType::PreciseTimer);
        connect(MyThreadQtimer,SIGNAL(timeout()),&obj,SLOT(MyTimerFunc()));
        MyThreadQtimer->start(MyTimerInterval);
        exec();
        if(MyThreadQtimer!=NULL)
        {
            MyThreadQtimer->deleteLater();
            MyThreadQtimer=NULL;
        }
    }
    

    这里我们使用connect函数将timesignal()信号和MyObject类的对象的MyTimerFunc()函数连接起来,那么对于这个函数,它的信号发起者依附于新线程,因为QTimer对象是在新线程中创建的,接收者同样也依附于新线程,因为MyObect类的对象也是在新线程中创建,此时的连接就是直接连接,那么槽函数就会在新线程中运行了。

    展开全文
  • qtimer

    2019-10-04 22:12:00
    QTimer QTimer提供单词计时器和重复计时器 slots void start([int msec]) void stop() sinals void timeout() 虚函数 virtual void timerEvent(QTimerEvent *e) ove...
  • QTimer 可能是小程序中最好用的魔方计时器。 使用 熟悉魔方计时器操作的魔友应该很容易就知道QTimer怎么用。需要注意的是,QTimer不鼓励大家随意修改自己的成绩,因此只有在完成的时候,左下角计时Tab会出现小红点,...
  • 目录标题 概述 QTimer 定时器(QTimer Class) 概述 权威资料 定时器精度 时间间隔 单次触发功能 开启(重启)/停止 运行状态 槽函数的绑定方式 示例 QT定时器事件(Timerevent) 概述 开启定时器(startTimer) 关闭定时器...
  • 2.6.4 Qtimer定时器介绍

    2021-10-15 16:22:31
    2.6.4 Qtimer定时器介绍 QTimer类提供了定时器功能,在指定的时间超时之后可以发出超时信号,可以单次或者重复定时。 QTimer使用方法比较简单:先创建一个QTimer定时器,使用start()函数设定定时的时间并开始计时。...
  • Qt QTimer

    2022-01-10 16:15:44
    Header: #include CMake: find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core) qmake: QT += core ...QTimer(QObject *parent = nullptr); QTimer类的构造函数。 vi

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,972
精华内容 5,988
关键字:

Qtimer