QT定时器+事件捕获

QT定时器类

定时器类的使用主要包括定时和启动两个步骤。要使用OTimer类,需要引用头文件:
#include <QTimer>
QTimer类常用的成员函数有

(1)void start(std::chrono::miliseconds msec):启动定时器,参数为定时时间(单位为毫秒),如:
        QTimer myTimer;                           //定义一个定时器对象
        myTimer.start(1000);                     //启动定时器,定时时间1000ms
(2)void stop():停止定时器。

(3)void setTimerType(Qt::TimerType type):设置定时器精度。
        Qt提供了三种定时策略,分别为:
            精确的定时(Qt::PreciseTimer,毫秒级精度)
            粗略的定时(Qt::CoarseTimer,5%左右的定时误差)--默认
            非常粗略的定时(Qt::VeryCoarseTimer,精度在1s左右)

(4)void singleShot(int msec, const QObject *receiver, const char*member):单次定时。
定时时间由参数msec指定,单位为ms。定时结束后会自动调用receiver的槽函数member。

定时结束,会自动发射信号timeout(),且OTimer类的信号只有timeout()。

UI界面控件

这里定时器主要的使用控件为LCD Number

定时器功能实现,主要是通过相应按键转到槽,调用定时器的几个函数,以下为部分代码,后续会有全部的代码展示。

void MainWindow::update()
{
    m_ftime += 0.1;
    ui ->lcdNumber->display(m_ftime);
}

void MainWindow::on_Timer_begin_clicked()
{
    m_timer.start(100);
}


void MainWindow::on_Timer_stop_clicked()
{
    m_timer.stop();
}


void MainWindow::on_pushButton_4_clicked()
{
    m_ftime = 0;
    ui ->lcdNumber->display(m_ftime);
}
事件与事件过滤器

事件是程序内部或外部产生的事情或某种动作的通称。Ot中常见事件包括鼠标事件、键盘事件、定时事件、上下文菜单事件、关闭事件、拖放事件、绘制事件等。
在Qt中,事件的类型在QEvent::Type中有着详细的定义。
系统可以捕获事件,然后根据事件的类型和来源进行处理。
有时开发者会希望拦截某个事件并进行处理,从而实现自定义的功能。

部分事件的解读:

QEvent::MouseButtonPress 鼠标按下时,触发该事件,对应的子类是 QMouseEvent

QEvent::MouseMove 鼠标移动时,触发该事件,对应的子类是 QMouseEvent

QEvent::MouseButtonRelease 鼠标释放时,触发该事件,对应的子类是 QMouseEvent

由于LCD Number控件没有clicked()信号,所以不能响应鼠标单击事件。如果想要实现单击LCDNumber控件暂停/启动计时、右击LCDNumber控件清零计时时间的功能,应该怎么办呢?
一种方法是用自定义类继承控件类,然后重写mousePressEvent事件的处理函数。
另一种方法是使用事件过滤器。
事件过滤器可以对控件的事件进行过滤和拦截,从而改变处理事件的方式。

事件过滤器的使用

(1)在目标对象上调用installEventFilter()函数注册事件过滤器。也可以使用removeEventFilter()函数删除已有的事件过滤器。

(2)向类中添加eventFilter()函数,并完成事件处理代码。

(3)确定事件的后续去向,即是否需要将事件传递给系统处理。如果在eventFilter()函数中返回false,那么事件将发送给系统。如果返回了true,那么该事件会被丢弃,后续的事件过滤器和系统都不能检测到这一事件。

时间过滤器要点:

1.首先需要在mainWindow主程序中安装事件过滤器

ui->lcdNumber->installEventFilter(this);

2.重定义eventFilter()函数(该函式是一个虚函数)

重写bool eventFilter(QObject *obj, QEvent *event),参数不可以改变,因为是虚函数。

bool MainWindow::eventFilter(QObject *obj,QEvent *event)
{
    if(obj == ui ->lcdNumber)
    {
        if (event->type() == QEvent::MouseButtonPress)
        {
            QMouseEvent *event2 = static_cast<QMouseEvent *>(event);
            if(event2 ->button() == Qt::LeftButton)
            {
                if(m_timer.isActive() == 1)
                {
                    m_timer.stop();
                }
                else
                {
                    m_timer.start(100);
                }
            }
            else if(event2 ->button() == Qt::RightButton)
            {
                m_ftime = 0;
                ui->lcdNumber->display(m_ftime);
            }
        }
    }
    return QObject::eventFilter(obj,event);
}

这里需要注意,一定要加上头文件因为缺少头文件,会导致static static_cast(event)函数发生错误。

#include <QEvent>
#include <QMouseEvent>
#include <QKeyEvent>
事件过滤器详解
void QObject::installEventFilter(QObject *filterObj)
bool eventFilter(QObject *obj, QEvent *event);

Qt的事件过滤由以上两个方法实现,首先安装一个事件过滤器,然后重写bool eventFilter(QObject *obj, QEvent *event)函数

filterObj表示事件筛选器对象,它接收发送到此QObject对象的所有事件。筛选器可以停止事件,也可以将事件转发给此QObject对象。事件过滤器filterObj通过它的eventFilter()函数接收并处理事件。

返回值:eventFilter()有返回值。

  • 如果返回true,表示事件过滤,不会发送到对象本身。
  • 如果返回false,表示事件未过滤,会通过event()方法将事件分发到对象。
  • 返回给基类进行处理,例:return QObject::eventFilter(obj, event)。

事件过滤器注册后,发送到控件的事件首先到达eventFilter()函数,然后在到达最终的目的地。

 源码示例:

mainwindow.h文件

#include <QTimer>
#include <QEvent>
#include <QMouseEvent>

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 update();

    void on_Timer_begin_clicked();

    void on_Timer_stop_clicked();

    void on_pushButton_4_clicked();

private:
    Ui::MainWindow *ui;

    QTimer m_timer;
    float  m_ftime;

    bool eventFilter(QObject *obj,QEvent *event);
};
#endif // MAINWINDOW_H

maindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(&m_timer,SIGNAL(timeout()),this,SLOT(update()));
    m_timer.setTimerType(Qt::PreciseTimer); //修改定时器策略为精确的定时
    m_ftime = 0;
    ui->lcdNumber->installEventFilter(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::update()
{
    m_ftime += 0.1;
    ui ->lcdNumber->display(m_ftime);
}

void MainWindow::on_Timer_begin_clicked()
{
    m_timer.start(100);
}


void MainWindow::on_Timer_stop_clicked()
{
    m_timer.stop();
}


void MainWindow::on_pushButton_4_clicked()
{
    m_ftime = 0;
    ui ->lcdNumber->display(m_ftime);
}

bool MainWindow::eventFilter(QObject *obj,QEvent *event)
{
   /* 这里使用的是lcdnumber控件,不支持键盘输入,QLineEdit控件支持键盘输入
    if(event->type() ==  QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
         if (keyEvent->key() == Qt::Key_Space)
         {
             m_ftime = 0;
             ui->lcdNumber->display(m_ftime);
         }

    }
    */
    if(obj == ui ->lcdNumber)
    {
        if (event->type() == QEvent::MouseButtonPress)
        {
            QMouseEvent *event2 = static_cast<QMouseEvent *>(event);
            //如果事件为鼠标按下事件,把QEvent转换为QMouseEvent
            if(event2 ->button() == Qt::LeftButton)
            {
                if(m_timer.isActive() == 1)
                {
                    m_timer.stop();
                }
                else
                {
                    m_timer.start(100);
                }
            }
            else if(event2 ->button() == Qt::RightButton)
            {
                m_ftime = 0;
                ui->lcdNumber->display(m_ftime);
            }
        }
    }

    return QObject::eventFilter(obj,event);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值