范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Qt开发鼠标事件

  引言
  个人认为,事件机制是Qt最难以理解且最为精妙的一部分。事件主要分为两种: 在与用户交互时发生 。比如按下鼠标(mousePressEvent),敲击键盘(keyPressEvent)等。 系统自动发生 ,比如计时器事件(timerEvent)等。
  在发生事件时(比如说上面说的按下鼠标),就会产生一个QEvent对象(这里是QMouseEvent,为QEvent的子类),这个QEvent对象会传给当前组件的event函数。如果当前组件没有安装 事件过滤器 (这个后面会提到),则会被event函数发放到相应的xxxEvent函数中(这里是mousePressEvent函数)。
  需要区分的是: 事件与信号并不相同。
  比如:鼠标单击按钮,鼠标事件(QMouseEvent),而按钮本身发射clicked()信号。一般而言我们只需要关注单击信号,不用考虑鼠标事件。但是当我们要对该按钮做额外操作,不想通过信号处理,此时事件就是一个很好的选择。关闭事件(QCloseEvent)是一个常用的事件。 一,事件
  Qt 中所有事件类都继承于 QEvent。在事件对象创建完毕后,Qt 将这个事件对象传递给 QObject 的 event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(eventhandler)。
  信号是通过connect()来绑定槽函数处理响应,那么事件是怎么处理的呢?
  处理事件有5种常用的方法: 重新实现部件的paintEvent()、mousePressEvent()等事件处理函数。这是最常用的一种方法,不过只能用来处理特定部件的特定事件 (即需要新建类去实现)  重新实现notify()函数。这个函数的功能强大,提供了完全的控制,可以再事件过滤器得到事件之间就获得他们。但是,它一次只能处理一个事件。 向QApplication对象上安装事件过滤器。因为一个程序只有一个QApplication对象,实现的功能和notify()函数相同,优点是可以同时处理多个事件。 重新实现event()函数。QObject类的event()函数可以在事件达到默认事件处理函数之前获得该事件。 在对象上安装事件过滤器。使用事件过滤器可以再一个界面类中同时处理不同子部件的事件 (在本类中实现)
  实际编程中最常用的是方法(1),其次是方法(5)。方法2要继承QApplication类,方法3需要全局的事件过滤器,减缓事件的传递。
  鼠标事件:
  常用的鼠标事件:(本篇处理事件用的是方法一:重写鼠标事件) void mousePressEvent(QMouseEvent *event); //单击 void mouseReleaseEvent(QMouseEvent *event); //释放 void mouseDoubleClickEvent(QMouseEvent *event); //双击 void mouseMoveEvent(QMouseEvent *event); //移动 void wheelEvent(QWheelEvent *event); //滑轮
  鼠标事件使用的时候,加头文件: #include
  重写事件框架:
  1️⃣鼠标按下事件 void Widget::mousePressEvent(QMouseEvent *event) {     // 如果是鼠标左键按下        if(event->button() == Qt::LeftButton){         ···     }     // 如果是鼠标右键按下     else if(event->button() == Qt::RightButton){        ···     } }
  2️⃣鼠标移动事件void Widget::mouseMoveEvent(QMouseEvent *event) {     // 这里必须使用buttons()     if(event->buttons() & Qt::LeftButton){  //进行的按位与        ···     } }
  默认情况下,触发事件需要点击一下,才能触发。可设置为自动触发:setMouseTracking(true);
  3️⃣鼠标释放事件void Widget::mouseReleaseEvent(QMouseEvent *event) {    ··· }
  4️⃣鼠标双击事件void Widget::mouseDoubleClickEvent(QMouseEvent *event) {     // 如果是鼠标左键按下     if(event->button() == Qt::LeftButton){                ···     } }
  5️⃣滚轮事件void Widget::wheelEvent(QWheelEvent *event) {     // 当滚轮远离使用者时     if(event->delta() > 0){         ···     }else{//当滚轮向使用者方向旋转时         ···     } }
  实例演示 (在label控件中,移动鼠标获取实时位置,并显示在界面上)创建mylabel类,基类设置为QLabel
  这里用了类似自定义控件的方法,对Mylabel类进行封装。设置基类QLabel 是为了在ui界面中提升label控件(即将label控件和Mylabel关联,提升时候必须二者基类相同)在mylabel.h中声明鼠标事件#pragma once #include   class mylabel : public QLabel { public:     mylabel(QWidget* parent = 0);     ~mylabel(); public:     //鼠标移动事件     void mouseMoveEvent(QMouseEvent* event);     //鼠标按下事件     void mousePressEvent(QMouseEvent* event);     //鼠标释放事件     void mouseReleaseEvent(QMouseEvent* event); };在mylabel.cpp中重写事件#include "mylabel.h" #include"QMouseEvent"   mylabel::mylabel(QWidget* parent) :QLabel(parent) {      } mylabel::~mylabel() {  } //鼠标移动显示坐标 void mylabel::mouseMoveEvent(QMouseEvent* event) {     if (event->buttons() & Qt::LeftButton)  //进行的按位与(只有左键点击移动才满足)     {          QString str = QString("Move:(X:%1,Y:%2)").arg(event->x()).arg(event->y());          this->setText(str);               }      } //鼠标按下显示"ok,mouse is press" void mylabel::mousePressEvent(QMouseEvent* event) {     setText("Ok, mouse is press");  } //鼠标释放清除显示 void mylabel::mouseReleaseEvent(QMouseEvent* event) {     setText(" "); }在主函数(QTest.cpp)中声明mylabel的类对象(即声明一个mylabel类的label控件)#include "qtest.h"  QTest::QTest(QWidget *parent)     : QWidget(parent) {     ui.setupUi(this);     //声明mylabel类的控件     mylabel* label1 = new mylabel(this);     label1->setGeometry(QRect(130, 100, 271, 161));     //设置边框     label1->setFrameShape(QFrame::Panel); }
  另外,当调用setMouseTracking(true);时(即设置鼠标状态为自动触发),需要将鼠标移动事件的if语句去掉(因为不需要点击触发了)
  修改maylabel.cpp事件:#include "mylabel.h" #include"QMouseEvent"   mylabel::mylabel(QWidget* parent) :QLabel(parent) {     //设置鼠标状态(自动触发)     setMouseTracking(true); } mylabel::~mylabel() {  } //鼠标移动显示坐标 void mylabel::mouseMoveEvent(QMouseEvent* event) {    QString str = QString("Move:(X:%1,Y:%2)").arg(event->x()).arg(event->y());    this->setText(str); } //鼠标按下显示"ok,mouse is press" void mylabel::mousePressEvent(QMouseEvent* event) {     setText("Ok, mouse is press");  } //鼠标释放清除显示 void mylabel::mouseReleaseEvent(QMouseEvent* event) {     setText(" "); }
  效果展示:
  这里用的是代码创建label控件,那么能不能用ui界面编辑然后在对label控件提升呢?
  答案是可以的,但是需要注意的是:此处不能选择全局包含
  否则会出现:
  我想其中的原因主要是因为:
  本实例是新建了一个mylabel类,而不是像QT常用控件(三)——自定义控件封装 - 唯有自己强大 - 博客园 (cnblogs.com)这篇博文中直接新添加了一个设计师界面类(即包含ui .h .cpp)。当选择全局包含时,就包含了主类。
  点击领取Qt学习资料+视频教程~「链接」
  其实也有解决的办法:需要在提升界面的头文件处,将工程目录下自定义控件的地址放于此处(本篇地址:C:/Users/WFD/Desktop/QTest/QTest/mylabel.h)
  二,事件的分发:event函数
  上面提到的xxxEvent函数,称为事件处理器(event handler)。而event函数的作用就在于事件的分发。如果想在事件的分发之前就进行一些操作,比如监听(阻塞)鼠标按下事件。
  如果希望在事件分发之前做一些操作,就可以重写这个 event()函数了。比如我们希望阻塞鼠标按下事件,那么我们就在新建的Mylabel类中重写event()函数(该类的父类是QLabel) 在Mylabel.h中声明event事件#include"qlabel.h" class Mylabel : public QLabel { public:     explicit Mylabel(QWidget* parent = 0);      //鼠标按下事件     void mousePressEvent(QMouseEvent* event);      //鼠标释放事件     void mouseReleaseEvent(QMouseEvent* event);     //声明event事件     bool event(QEvent* e); };在Mylabel.cpp中重写event事件。#include "Mylabel.h" #include"QMouseEvent"  Mylabel::Mylabel(QWidget* parent) :QLabel(parent) {  }  //重写鼠标按下事件 void Mylabel::mousePressEvent(QMouseEvent* event) {     this->setText(QString("mouse is press x:%1,y:%2").arg(event->x()).arg(event->y())); } //重写鼠标释放事件 void Mylabel::mouseReleaseEvent(QMouseEvent* event) {     this->setText("mouse is release "); } //重写event事件 bool Mylabel::event(QEvent* e) {     //如果鼠标按下,再事件分发中做拦截     if (e->type()==QEvent::MouseButtonPress)     {         //静态转换(将QEvent的对象转换为QMouseEvent对象)         QMouseEvent* event = static_cast(e);         this->setText(QString("event mouse is press x:%1,y:%2").arg(event->x()).arg(event->y()));         return true;//返回ture,说明用户自己处理事件,不往下分发(即拦截上面的按下事件)     }     return QLabel::event(e); }
  点击鼠标可以看到,触发的是event的事件(即阻塞了mousePressEvent的事件)。特别需要注意的是:在将不需要阻塞分发的时候,需要分发给父类的event函数处理。即(return QLable::event(e);)
  由此可以见,event()是一个集中处理不同类型的事件的地方。如果你不想重写一大堆事件处理器,就可以重写这个 event()函数,通过 QEvent::type()判断不同的事件。鉴于重写 event()函数需要十分小心注意父类的同名函数的调用,一不留神就可能出现问题,所以一般还是建议只重写事件处理器(当然,也必须记得是不是应该调用父类的同名处理器)。三,事件过滤器(Even Filter)
  某些应用场景下,需要拦截某个组件发生的事件,让这个事件不再向其他组件进行传播,这时候可以为这个组件或其父组件安装一个事件过滤器,该过滤器在event分发之前进行拦截。
  事件的过滤有两个步骤:
  1️⃣对QObject组件安装过滤器(调用installEvenFilte r 函数) void QObject::installEventFilter ( QObject * filterObj );
  参数filterobj 是指谁为组件安装过滤器(一般是父类)这个函数接受一个 QObject *类型的参数。记得刚刚我们说的,eventFilter()函数是 QObject 的一个成员函数,因此,任意 QObject 都可以作为事件过滤器(问题在于,如果你没有重写 eventFilter()函数,这个事件过滤器是没有任何作用的,因为默认什么都不会过滤)。已经存在的过滤器则可以通过QObject::removeEventFilter()函数移除。我们可以向一个对象上面安装多个事件处理器 ,只要调用多次installEventFilter()函数。如果一个对象存在多个事件过滤器,那么,最后一个安装的会第一个执行,也就是后进先执行的顺序。
  2️⃣事件过滤器的重写(evenFilter函数) virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );
  可以看到,函数有两个参数,一个为具体发生事件的组件,一个为发生的事件(产生的QEvent对象)。当事件是我们感兴趣的类型,可以就地进行处理,并令其不再转发给其他组件。函数的返回值也是bool类型,作用跟even函数类似,返回true为不再转发,false则让其继续被处理。
  点击领取Qt学习资料+视频教程~「链接」
  实例:通过事件过滤器阻塞上面代码中的鼠标按下事件#include "qtest.h" #include"qmouseevent"  QTest::QTest(QWidget *parent)     : QWidget(parent) {     ui.setupUi(this);     //第一步:给label添加过滤器     ui.label->installEventFilter(this);   } //第二步:重写过滤事件 bool QTest::eventFilter(QObject* obj, QEvent* e) {     if (obj == ui.label)     {         //如果鼠标按下,再事件分发中做拦截         if (e->type() == QEvent::MouseButtonPress)         {             QMouseEvent* event = static_cast(e);             ui.label->setText(QString("eventfilter mouse is press x:%1,y:%2").arg(event->x()).arg(event->y()));             return true;//返回ture,说明用户自己处理事件,不往下分发(即拦截上面的按下事件)         }     }     return QWidget::eventFilter(obj, e); }  //重写鼠标按下事件 void QTest::mousePressEvent(QMouseEvent* event) {     ui.label->setText(QString("mouse is press x:%1,y:%2").arg(event->x()).arg(event->y())); }  //重写事件分发 bool QTest::event(QEvent* e) {     //如果鼠标按下,再事件分发中做拦截     if (e->type() == QEvent::MouseButtonPress)     {         QMouseEvent* event = static_cast(e);         ui.label->setText(QString("event mouse is press x:%1,y:%2").arg(event->x()).arg(event->y()));         return true;//返回ture,说明用户自己处理事件,不往下分发(即拦截上面的按下事件)     }     return QWidget::event(e); }
  运行结果:
  可以看到在过滤器事件中就监听了鼠标按压(即阻塞了后面的事件分发和鼠标按压)

孩子早产遇险后,明星爸妈满心绝望,有的硬汉落泪,有的果断结扎因被质疑女儿是代孕生的,好友晒出了张碧晨临产时的照片头发凌乱的张碧晨吸着氧,隆起的肚子上绑着胎心监测的仪器,丝毫没有女明星的光鲜亮丽。孩子降生后,憔悴的张碧晨与很小一只的女儿合影,香港珍宝海鲜坊海上餐厅,托离香港后在南海沉没难以打捞珍宝海鲜坊曾是香港知名地标,陪伴香港人超过40多年的水上餐厅珍宝海鲜坊,结束营业后找不到新的经营者接手,在六月十四日被拖离香港避风塘,近日传出在中国南海海域沉没,恐怕难以打捞,曾经中超最新积分榜泰山3球完胜攀升第3,国安狂轰4球大胜深圳今天,中超联赛第5轮继续激战,山东泰山30完胜大连人,升至积分榜第3位,两位外援费莱尼和莫伊塞斯分别破门,大连人不败战绩被终结北京国安41大胜深圳队,积分超越对手,张玉宁梅开二度天新仙剑奇侠传官宣,李逍遥赵灵儿颜值遭嫌弃,网友怎么敢接仙剑系列都快被翻拍烂了,我记得鞠婧祎和陈哲远拍了一个版本,之前杨幂公司的小演员黄杨钿甜也演了一回赵灵儿,后面据说许凯和虞书欣还会拍一个版本,21号上午,又一新版仙剑奇侠传官宣演员全国产航母下水当天,印度悄然公布国产电磁弹射项目,想法太简单了近日,我国国产航母003号,进行了下水和命名仪式,命名为福建舰。该舰采用了电磁弹射系统,福建舰的服役是我国第1艘平甲板弹射的航空母舰。003号也是亚洲地区最大的航母主舰。这一消息一金铲铲超模3费卡这个版本冰鸟真的是太强了,做为一个三费卡,完完全全的超模了,有aoe伤害,有减魔抗,羁绊还多,装备上法转科技枪,真的是伤害回复拉满,施法也挺智能的(想起EZ施法智障,满屏都是敌人,爸爸坐牢妈妈离家出走,她6岁撑起三代人的家,无数国人为她点赞孩子,对不起!女人吻了一下女婴的额头,说完就毅然决然地拎起早已收拾好的包裹离去了。女人的背影逐渐变得模糊,直到彻底消失在朦胧的月色当中。此刻,襁褓中正在熟睡的女婴,并不知道自己接下深化金砖合作淬炼金砖成色自2006年序幕开启,金砖国家合作已走过16个年头。金砖国家优势互补,不断深挖合作潜力,拓宽合作领域,成为新兴市场和发展中国家联合自强的典范。在当前世纪疫情同百年变局叠加共振国际格韩雨芹到底有多美,看完这几张高清大图你就知道了韩雨芹到底有多美,看完这几张高清大图你就知道了,说起韩雨芹,大家都不陌生。韩雨芹出道不久就与吴奇隆合作演出少年王,饰演一名流着蓝血的女强人大乔,凭借此剧韩雨芹获得一定的关注度。而后找王心凌代言鸿星尔克,这届网友太会玩了最近,国内顶流鸿星尔克又火了不过这次火的原因不是捐款而是源于这段时间火得没边的国民顶流女神王心凌事情是这样的王心凌在社交平台里说发布了一张日常穿搭照结果有眼尖的网友发现身上穿的不是重庆男子发帖举报当地一团伙组织幼女卖淫,曾被警方要求删除网上举报信息学生妹有没有需要的?3月19日,重庆酉阳县车田乡的毛先生在微信聊天群里无意中看到一条招嫖信息,抱着好玩的心态便加了对方微信了解情况。令毛先生想不到的是,对方发来的都是12岁左右的女
中新体坛相比输韩国,中国足球找到了更重要的东西来源中新体坛在北京时间12日晚结束的U20亚洲杯14决赛中,中国队苦战加时赛,最终13不敌韩国队,无缘晋级4强,距离打破18年无缘世青赛的尴尬记录,只剩下一步之遥。虽然有些许遗憾,中国自主研制的太赫兹探测设备在南极成功运行中新社南京3月13日电(记者杨颜慈)中新社记者13日从中国科学院紫金山天文台获悉,在中国第39次南极科学考察期间,由该台牵头完成了南极内陆太赫兹天文试观测和通信收发等实验。这是中国3。15新能源汽车维权调查壁垒缺失下的无序之争,动力失速续航虚标虚假营销成共性红周刊丨李洪力编者按正值3。15来临之际,红周刊调查部分新能源车企终端市场表现时发现,虚假营销随意修改格式条款电池故障车机系统死机卡顿不按时交付续航虚标严重自燃频发等多种问题在很多观点上汽集团代表建议加强对高校智能网联汽车卡脖子技术扶持文懂车帝原创李德喆懂车帝原创行业懂车帝从上汽集团获悉,在今年的全国两会上,三位来自上汽集团的全国人大代表姚佐平丁波和刘懿艳围绕汽车产业高质量发展积极建言献策。上汽集团代表建议加强对紫金山天文台提前两周预警30米级近地小行星飞掠地月系统IT之家3月13日消息,IT之家从中国科学院紫金山天文台官网获悉,国际小行星中心(MPC)2月27日发布公告,确认中国科学院紫金山天文台(紫台)新发现的近地小行星2023DU是一颗高端旗舰机发布将至华为在用实际行动兑现承诺中国网科技3月13日讯(记者单征宇)3月9日,华为终端BGCEO余承东率先曝出华为P60Pro拍摄图片样张,表明华为P60系列上市只是时间问题。上半年一季度,基本是各家厂商推出旗下售出2。6亿部!三星失去中国市场仍是全球第一,折射出什么信号?在阅读此文前,诚邀您点击一下关注,既方便您进行讨论与分享,又给您带来不一样的参与感,感谢您的支持。三星的知名度不用多说,属于世界知名大企业,全球市场占比惊人。三星公司旗下的电子产品曹操平定河北一系列的意外事件这么近那么美周末到河北河北文旅看图识景奥运之城张家口等你来大美秦皇岛奋进新时代建安五年(公元200年),官渡之战后,袁绍损失惨重,不光是士兵的损失,更有田丰颜良文丑张颌高览等纷纷被看广告免费听歌音乐APP真躺平了?如何优雅地从用户兜里掏钱?从上个世纪开始,中国互联网公司就因这节必修课而头大。时至今日,仍有不少APP行走在挂科的边缘。比如最近经常上热搜的视频平台,每次引起网友围观,几乎都是因为对啊网违反广告法被罚宣传用语与事实不符中国经济网北京3月13日讯近日,北京市市场监督管理局网站公布的行政处罚决定书(京技管市监处罚202337号)显示,北京对啊网教育科技有限公司因违反广告法相关规定,被北京经济技术开发吉赛尔邦辰穿丁字裤化身脱衣舞娘,为拍广告大玩性感惹争议42岁的吉赛尔邦辰(GiseleBundchen)穿着丁字裤大秀性感身材,为拍新广告化身脱衣舞娘周五,吉赛尔邦辰摆脱了她一贯的好女孩形象,化身性感脱衣舞娘,为拍摄新广告全情投入。汤