Qt3学习使用事件过滤器(二)

上一篇我们根据实际使用提出了事件过滤器的需求,那么现在就部署吧,首先

#include "mycapture.h"
#include <qapplication.h>
#include <qpainter.h>
#include <qstring.h>
#include <qtimer.h>
#include <chrono>


ScreenCaptureWidget::ScreenCaptureWidget(QWidget* parent) : QWidget(parent)
{
    // 确保接收鼠标事件
    setMouseTracking(true);
    m_lastClickTime = 0;
    m_clickCount = 0;
    m_lastRightClickTime = 0;
    m_rightClickCount = 0;
      m_clicknum = 0;
}


bool ScreenCaptureWidget::eventFilter(QObject *o, QEvent *e)
{
    if (!o ||!e)
        return true;
    

    if (o == this && e->type() == QEvent::MouseButtonPress)
    {
        
        int interval = QApplication::doubleClickInterval();
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(e);
        if (mouseEvent->button() == Qt::LeftButton)
        {
            
            auto currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
            long long atime = currentTime - static_cast<long long>(m_lastClickTime);
            if (currentTime - static_cast<long long>(m_lastClickTime) < static_cast<long long>(QApplication::doubleClickInterval()))
            {
                qDebug("the mouse default interval (%d).", QApplication::doubleClickInterval());
                m_clickCount++;
            }
            else
            {
                m_clickCount = 1;
            }
            m_lastClickTime = currentTime;
            m_clicknum++;
            qDebug("The mouse two interval (%lld) It is the (%d) times.", atime, m_clicknum); 
            if (m_clickCount == 1)
            {
                QTimer::singleShot(QApplication::doubleClickInterval(), this, SLOT(handleSingleClick()));
            }
            else if (m_clickCount == 2)
            {
                handleDoubleClick(mouseEvent);
                m_clickCount = 0;
                return true;
            }
        }
        else if (mouseEvent->button() == Qt::RightButton)
        {
            auto currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
            if (currentTime - m_lastRightClickTime < QApplication::doubleClickInterval())
            {
                m_rightClickCount++;
            }
            else
            {
                m_rightClickCount = 1;
            }
            m_lastRightClickTime = currentTime;


            if (m_rightClickCount == 1)
            {
                QTimer::singleShot(QApplication::doubleClickInterval(), this, SLOT(handleSingleRightClick()));
            }
            else if (m_rightClickCount == 2)
            {
                handleDoubleRightClick(mouseEvent);
                m_rightClickCount = 0;
                return true;
            }
        }
    }
    return QWidget::eventFilter(o, e);
}


void ScreenCaptureWidget::handleSingleClick()
{
    qDebug("Single click detected.");
    // 取消定时器,防止误触发双击事件
    QTimer::singleShot(0, this, SLOT(cancelClickCount()));
}



void ScreenCaptureWidget::handleDoubleClick(QMouseEvent *event)
{
    qDebug("Double click detected at (%d, %d).", event->x(), event->y());
}


void ScreenCaptureWidget::handleSingleRightClick()
{
    qDebug("Single right click detected.");
    QTimer::singleShot(0, this, SLOT(cancelRightClickCount()));
}


void ScreenCaptureWidget::handleDoubleRightClick(QMouseEvent *event)
{
    qDebug("Double right click detected at (%d, %d).", event->x(), event->y());
}


void ScreenCaptureWidget::cancelClickCount()
{
    m_clickCount = 0;
}


void ScreenCaptureWidget::cancelRightClickCount()
{
    m_rightClickCount = 0;
}


void ScreenCaptureWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawText(10, 10, "Hello, World!");
    painter.end();
}

以上代码实现了在当前窗口根据不同鼠标点击触发事件,并设置了相应的槽函数,注意其中的时间判断需要使用chrono库,由于qt3没有 qint64,那么尝试改成int行不行了,不行,因为计算时间间隔是按毫秒来计算的(鼠标双击事件都是毫秒级200-900ms)这就会导致计算出来的时间最小分辨率是1s不满足要求,使用int也会导致utc时间越界的问题,所以必须使用long long,还需要注意的是 qDebug("The mouse two interval (%lld) It is the (%d) times.", atime, m_clicknum); ,这里面lld是对这个long long类型的调用,如果写成d程序也能运行,但是后面那个d就显示不出来了,属于不容易发现的问题

qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
                if (currentTime - m_lastClickTime < QApplication::doubleClickInterval())

,以上代码实现了对指定窗口应用了事件过滤器,要生效需要使用如下:

#include <qapplication.h>
#include "mycapture.h"


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    ScreenCaptureWidget widget;
widget.resize(350,260);
    widget.show();
    // 为 widget 安装事件过滤器
    widget.installEventFilter(&widget);
 QObject::connect(&widget, SIGNAL(clickedOnExitArea()), &app, SLOT(quit()));
    QObject::connect( &app, SIGNAL(lastWindowClosed()),
                       &app, SLOT(quit()) );
    return app.exec();
}

可以看到有一条对自己注册了事件过滤器,代码耦合度很高,那么,可不可以将事件过滤器提出出来,降低耦合度呢,widget.installEventFilter(&widget);这样的调用明显在类自己内部完成,以下是修改代码,包装成独立的类

#include "GlobalKeyFilter.h"


GlobalKeyFilter::GlobalKeyFilter(QObject *parent) : QObject(parent)
{
}


bool GlobalKeyFilter::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = (QKeyEvent *)event;
        auto it = keyCallbacks.find(keyEvent->key());
        if (it!= keyCallbacks.end())
        {
            it->second();
            return true;
        }
    }
    return QObject::eventFilter(obj, event);
}


void GlobalKeyFilter::setKeyCallback(Qt::Key key, std::function<void()> callback)
{
    keyCallbacks[key] = callback;
}


//GlobalKeyFilter.h"文件内容如下
#ifndef GLOBALKEYFILTER_H
#define GLOBALKEYFILTER_H

#include <qobject.h>
#include <qevent.h>
#include <iostream>
#include <map>
#include <functional>

class GlobalKeyFilter : public QObject
{
    Q_OBJECT
public:
    explicit GlobalKeyFilter(QObject *parent = nullptr);
    bool eventFilter(QObject *obj, QEvent *event);

    // 设置特定按键组合的回调函数
    void setKeyCallback(Qt::Key key, std::function<void()> callback);

private:
    // 存储按键和对应回调函数的映射
    std::map<Qt::Key, std::function<void()>> keyCallbacks;
};

#endif // GLOBALKEYFILTER_H










好的,GlobalKeyFilter globalFilter;
    app.installEventFilter(&globalFilter);
    globalFilter.setKeyCallback(Qt::Key_Escape, handleEsc);运行一下,报错:原因如下: 无法从“int”转换为“const Qt::Key”
.\MouseEventFilter.cpp(12): note: 转换为枚举类型需要显式强制转换(static_cast、C 样式强制转换或带圆括号函数样式强制转换)
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.42.34433\include\xtree(1397): note: 或    “std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const Qt::Key,std::function<void (void)>>>>> std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::find(const _Other &) const”

修改方案

  1. 将 keyEvent->key() 的结果显式转换为 Qt::Key 类型,使用 static_cast<Qt::Key>(keyEvent->key())
     

代码如下:

#include "MouseEventFilter.h"

GlobalKeyFilter::GlobalKeyFilter(QObject *parent) : QObject(parent)
{
}

bool GlobalKeyFilter::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
       QKeyEvent *keyEvent = (QKeyEvent *)event;
        Qt::Key key = static_cast<Qt::Key>(keyEvent->key());
        auto it = keyCallbacks.find(key);
        if (it!= keyCallbacks.end())
        {
            it->second();
            return true;
        }
    }
    return QObject::eventFilter(obj, event);
}

void GlobalKeyFilter::setKeyCallback(Qt::Key key, std::function<void()> callback)
{
    keyCallbacks[key] = callback;
}

 main.cpp调用和回调函数:

#include <qapplication.h>
#include "MouseEventFilter.h"
#include "capture.h"
void handleEsc()
{
    qDebug( "Esc key pressed globally.");
}

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    ScreenCaptureWidget widget;
    widget.show();
GlobalKeyFilter globalFilter;
    app.installEventFilter(&globalFilter);
    globalFilter.setKeyCallback(Qt::Key_Escape, handleEsc);

QObject::connect(&app, SIGNAL(lastWindowClosed()),
        &app, SLOT(quit()));
    return app.exec();
}

这样就行了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/956090.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

游戏引擎学习第80天

Blackboard&#xff1a;增强碰撞循环&#xff0c;循环遍历两种类型的 t 值 计划对现有的碰撞检测循环进行修改&#xff0c;以便实现一些新的功能。具体来说&#xff0c;是希望处理在游戏中定义可行走区域和地面的一些实体。尽管这是一个2D游戏&#xff0c;目标是构建一些更丰富…

EMS专题 | 守护数据安全:数据中心和服务器机房环境温湿度监测

您需要服务器机房温度监测解决方案吗&#xff1f; 服务器机房是企业中用于存储、管理和维护服务器及其相关组件的设施。服务器机房通常位于数据中心内&#xff0c;是一个专门设计的物理环境&#xff0c;旨在确保服务器的稳定运行和数据的安全性。服务器机房主要起到存储和管理数…

4 AXI USER IP

前言 使用AXI Interface封装IP&#xff0c;并使用AXI Interface实现对IP内部寄存器进行读写实现控制LED的demo&#xff0c;这个demo是非常必要的&#xff0c;因为在前面的笔记中基本都需哟PS端与PL端就行通信互相交互&#xff0c;在PL端可以通过中断的形式来告知PS端一些事情&…

网络编程 | UDP套接字通信及编程实现经验教程

1、UDP基础 传输层主要应用的协议模型有两种&#xff0c;一种是TCP协议&#xff0c;另外一种则是UDP协议。在上一篇博客文章中&#xff0c;已经对TCP协议及如何编程实现进行了详细的梳理讲解&#xff0c;在本文中&#xff0c;主要讲解与TCP一样广泛使用了另一种协议&#xff1a…

A5.Springboot-LLama3.2服务自动化构建(二)——Jenkins流水线构建配置初始化设置

下面我们接着上一篇文章《A4.Springboot-LLama3.2服务自动化构建(一)——构建docker镜像配置》继续往下分析,在自动化流水线构建过程当中的相关初始化设置和脚本编写。 一、首先需要先安装Jenkins 主部分请参考我前面写的一篇文章《Jenkins持续集成与交付安装配置》 二、…

开发神器之cursor

文章目录 cursor简介主要特点 下载cursor页面的简单介绍切换大模型指定ai学习的文件指定特定的代码喂给ai创建项目框架文件 cursor简介 Cursor 是一款专为开发者设计的智能代码编辑器&#xff0c;集成了先进的 AI 技术&#xff0c;旨在提升编程效率。以下是其主要特点和功能&a…

基于机器学习随机森林算法的个人职业预测研究

1.背景调研 随着信息技术的飞速发展&#xff0c;特别是大数据和云计算技术的广泛应用&#xff0c;各行各业都积累了大量的数据。这些数据中蕴含着丰富的信息和模式&#xff0c;为利用机器学习进行职业预测提供了可能。机器学习算法的不断进步&#xff0c;如深度学习、强化学习等…

【王树森搜索引擎技术】概要01:搜索引擎的基本概念

1. 基本名词 query&#xff1a;查询词SUG&#xff1a;搜索建议文档&#xff1a;搜索结果标签/筛选项 文档单列曝光 文档双列曝光 2. 曝光与点击 曝光&#xff1a;用户在搜索结果页上看到文档&#xff0c;就算曝光文档点击&#xff1a;在曝光后&#xff0c;用户点击文档&…

图论DFS:黑红树

我的个人主页 {\large \mathsf{{\color{Red} 我的个人主页} } } 我的个人主页 往 {\color{Red} {\Huge 往} } 往 期 {\color{Green} {\Huge 期} } 期 文 {\color{Blue} {\Huge 文} } 文 章 {\color{Orange} {\Huge 章}} 章 DFS 算法&#xff1a;记忆化搜索DFS 算法&#xf…

ros2-7.5 做一个自动巡检机器人

7.5.1 需求及设计 又到了小鱼老师带着做最佳实践项目了。需求&#xff1a;做一个在各个房间不断巡逻并记录图像的机器人。 到达目标点后首先通过语音播放到达目标点信息&#xff0c; 再通过摄像头拍摄一张图片保存到本地。 7.5.2 编写巡检控制节点 在chapt7_ws/src下新建功…

告别繁琐编译!make和makefile的便捷之道

Linux系列 文章目录 Linux系列前言一、make/makefile是什么&#xff1f;二、make/makefile的使用2.1、语法规则2.2、依赖关系和依赖方法2.3、清理可执行文件2.4、执行依据 三、循环依赖问题总结 前言 上一篇博客给大家分享了在Linux下编译源代码的两个工具&#xff0c;gcc和g…

【鸿蒙】0x02-LiteOS-M基于Qemu RISC-V运行

OpenHarmony LiteOS-M基于Qemu RISC-V运行 系列文章目录更新日志OpenHarmony技术架构OH技术架构OH支持系统类型轻量系统&#xff08;mini system&#xff09;小型系统&#xff08;small system&#xff09;标准系统&#xff08;standard system&#xff09; 简介环境准备安装QE…

C语言初阶习题【29】杨氏矩阵

1. 题目描述——杨氏矩阵 有一个数字矩阵&#xff0c;矩阵的每行从左到右是递增的&#xff0c;矩阵从上到下是递增的&#xff0c;请编写程序在这样的矩阵中查找某个数字是否存在。 要求&#xff1a;时间复杂度小于O(N); 2. 思路 3. 代码实现1 #include<stdio.h>void fin…

Cloud Foundry,K8S,Mesos Marathon弹性扩缩容特性对比

一、Cloud Foundry 使用Scaling an Application Using App Autoscaler插件&#xff0c;基于资源使用情况触发简单扩缩容 CPU、内存、Http带宽、延时等 监控这些资源的使用情况决定扩缩容策略&#xff1a;实例是增加还是减少 Instance Limits 限制实例数量范围&#xff0c;定义…

中职网络建设与运维ansible服务

ansible服务 填写hosts指定主机范围和控制节点后创建一个脚本&#xff0c;可以利用简化脚本 1. 在linux1上安装系统自带的ansible-core,作为ansible控制节点,linux2-linux7作为ansible的受控节点 Linux1 Linux1-7 Yum install ansible-core -y Vi /etc/ansible/hosts 添加…

【BUUCTF】[GXYCTF2019]BabySQli

进入页面如下 尝试万能密码注入 显示这个&#xff08;qyq&#xff09; 用burp suite抓包试试 发现注释处是某种编码像是base编码格式 MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5 可以使用下面这个网页在线工具很方便…

迅为瑞芯微RK3562开发板/核心板应用于人脸跟踪、身体跟踪、视频监控、自动语音识别(ASR)、图像分类驾驶员辅助系统(ADAS)...

可应用于人脸跟踪、身体跟踪、视频监控、自动语音识别(ASR)、图像分类驾驶员辅助系统(ADAS)、车牌识别、物体识别等。iTOP-3562开发板/核心板采用瑞芯微RK3562处理器&#xff0c;内部集成了四核A53Mali G52架构&#xff0c;主频2GHZ&#xff0c;内置1TOPSNPU算力&#xff0c;RK…

蓝桥杯单片机基础部分——5、DS18B20温度传感器

前言 好久没有更新关于蓝桥杯单片机相关的模块了&#xff0c;今天更新一下数字温度传感器DS18B20的相关应用 单线数字温度计DS1820介绍 DS1820数字温度计提供9位(二进制)温度读数&#xff0c;指示器件的温度。信息经过单线接口送入DS1820 或从 DS1820 送出&#xff0c;因此从…

python爬虫入门(实践)

python爬虫入门&#xff08;实践&#xff09; 一、对目标网站进行分析 二、博客爬取 获取博客所有h2标题的路由 确定目标&#xff0c;查看源码 代码实现 """ 获取博客所有h2标题的路由 """url "http://www.crazyant.net"import re…

nginx 配置代理,根据 不同的请求头进行转发至不同的代理

解决场景&#xff1a;下载发票的版式文件&#xff0c;第三方返回的是url链接地址&#xff0c;但是服务是部署在内网环境&#xff0c;无法访问互联网进行下载。此时需要进行走反向代理出去&#xff0c;如果按照已有套路&#xff0c;就是根据不同的访问前缀&#xff0c;跳转不同的…