首页 > 其他分享 >QT定时器+事件捕获

QT定时器+事件捕获

时间:2024-10-11 15:47:37浏览次数:3  
标签:event 定时器 QT void MainWindow ftime 事件 ui 捕获

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);
}

标签:event,定时器,QT,void,MainWindow,ftime,事件,ui,捕获
From: https://blog.csdn.net/m0_64384363/article/details/142856296

相关文章

  • MQTT
    安装服务端EMQX客户端MQTTXJava集成SrpingBootpom.xml<dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-mqtt</artifactId></dependency><dependency><groupId&g......
  • c# 捕获系统快捷键并响应
    privatevoidGlobalKeyCapture_KeyDown(objectsender,KeyEventArgse){//判断当前进程是否是活动进程,以决定是否响应varcurrentProcess=getActiveProcess();if(currentProcess.Id!=Process.GetCurrentProcess().Id)return;if(e.KeyCode......
  • Qt - 将窗体变为顶层窗体
    1、将窗体变为顶层窗体(activateWindow();和raise())我们知道,在windows上通过鼠标双击某应用程序图标,该应用程序往往会以顶层窗口的形式呈现在我们面前,但是对于一个已经打开的非顶层窗口,我们怎么将其激活为顶层窗口呢?       要达到激活,这个必须要满足两个条件,第一,必须......
  • 基于YOLO11/v10/v8/v5深度学习的安检X光危险品检测与识别系统设计与实现【python源码+
    《博主简介》小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~......
  • Qt - 在父窗口中创建子窗口需要注意的事项
    Qt在父窗口中创建子窗口需要注意的事项: 一、QWidget1、《在QWidget下创建同类型的子窗口》指定了父对象:w=newWidgetSon(this)窗口就不是独立的,会嵌入到父窗口里。窗口一起显示。而且显示子窗口可以不用调用显示窗口函数,不调用的话也可以显示子窗口。不指定父对象:w=ne......
  • 如何用PyQt5创建多个窗口,同时获取多个U盘内的文件的名称,并分别在对应窗口打印文件名,要
    在PyQt5中,你可以使用QThread创建多个线程来并行处理每个U盘的文件名获取任务。每个线程负责扫描一个U盘的文件,同时在主窗口显示结果。以下是一个示例代码,用来创建多个窗口,同时在每个窗口中显示各自的U盘文件名:每个窗口使用QWidget。使用QThread创建后台线程获取U......
  • 【Qt】QStandardItem和QStandardItemModle以及QModelIndex的关系
    在Qt框架中,QStandardItem、QStandardItemModel和QModelIndex是用来处理表格和数据视图的关键类。以下是它们之间的关系和用途:QStandardItemQStandardItem是QStandardItemModel中用来表示单个项的类。它可以包含数据(如文本、图标、复选框状态等)和子项(用于树结构)。QSt......
  • 使用Qt Creator创建项目
    个人主页:C++忠实粉丝欢迎点赞......
  • Qt 4 下载地址(附安装教程)
    Qt4下载地址(附安装教程)获取Qt4现在去Qt官网下载老版本的Qt,会提示DownloadfromyourIPaddressisnotallowed.如果想要点进去下载,就要挂梯子。然而,在知道地址的情况下,可以不挂梯子,直接把链接丢到迅雷里面就可以下载了。这对Qt4和5都适用:可以根据下载地址的规律......
  • STM32中实现下降沿捕获(HAL库)
    配置步骤:1、配置时基工作参数HAL_TIM_IC_Init();主要配置其中的instanceinitautorelaodpreloadcountermodeperiodprescaler2、msp初始化HAL_TIM_IC_MspInit(TIM_HandleTypeDef*htim) __HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();  HAL_NV......