鼠标事件

1、Qt使用QMouseEvent类来描述与鼠标有关的信息,比如鼠标的位置坐标,键是否被按下等,使用枚举类型QEvent::Type描述与鼠标有关的事件,比如QEvent::MouseButtonPress表示鼠标按下事件,QEvent::MouseMove表示鼠标移动事件等。

2、是否接收鼠标事件,最好明确的调用QEvent::ignore()和QEvent::accept()函数。

3、下面是Qt在默认情况下对鼠标事件的处理,

①、注意:只有在按下鼠标按钮(左、右、中键都可)时才会发生鼠标移动事件(即QEvent::MouseMove),使用QWidget :: setMouseTracking()函数启用鼠标跟踪后,就即使不按下鼠标按钮也会产生鼠标移动事件。

②、Qt在部件内按下鼠标按钮时会自动抓取鼠标,也就是说,当按下鼠标后,将鼠标移除该小部件将继续接收鼠标事件,直到最后一个鼠标按钮被释放。可使用QWidget::grabMouse()函数抓取鼠标,使用QWidget::releaseMouse()函数释放鼠标抓取。

4、Qt使用枚举类型Qt::MouseButton来描述鼠标的信息,下表为该枚举定义的部分成员注意:QMouseButtons(最后多一个s)的类型为


5、下面为QMouseEvent类中的成员函数①、QMouseEvent( Type type, const QPointF &localPos, Qt::MouseButton button,

Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);

 type:表示鼠标事件的类型,必须是QEvent::MouseButtonPress、

QEvent::MouseButtonRelease、QEvent::MouseButtonDblClick、

QEvent::MouseMove之一。

localPose:鼠标光标的位置。其中QPointF是一个用于描述点的类,该类类似于QPoint,只是QPointF能接受浮点类型的坐标值,比如QPointF pf(33.3, 22.4),表示创建一个位于(33.3 , 22.4)的点。

 button:表示产生鼠标事件的按钮,若事件类型是MouseEvent,则此值是Qt::NoButton

buttons:产生鼠标事件时哪些鼠标按钮处于按下状态。

 modifiers:键盘修饰键

说明:这是QMouseEvent类的构造函数之一(共有4个),本文仅列举这一个,构造函数可以用于创建QMouseEvent类型的自定义事件,构造函数的参数虽然较多,但是,这些参数只是为创建的事件提供了一些必要的信息而已。

示例:

QMouseEvent e(QEvent::MouseButtonPress, QPointF(33,33),

Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);

表示创建一个类型为QEvent::MouseButtonPress的鼠标按下事件,产生该事件时鼠标的光标位于(33,33)处,该事件是由鼠标左键产生的,且产生该事件时鼠标左键处于按下状态,且没有键盘修饰键被按下。创建该自定义事件后,可以使用sendEvent进行发送,并使用部件类的event()函数接收并处理该事件。

②、Qt::MouseEventSource source() const; //qt5.3 返回鼠标事件的来源信息。鼠标事件除了可以来自于物理鼠标之外,还可以来自于其他来源,比如触摸屏的仿真鼠标事件。鼠标事件的来源使用枚举Qt::MouseEventSource来描述,该枚举可取以下值。


③、Qt::MouseButton button() const; //返回产生鼠标事件的按钮

Qt::MouseButtons buttons() const; //返回产生鼠标事件时处于按下状态的按钮。

以上两函数的区别在于buttons返回的值是Qt::MouseButtons类型,这是一个QFlags模板类型,而Qt::MouseButton仅仅是一个枚举类型,因此buttons函数的返回值可以是Qt::LeftButton, Qt::RightButton, Qt::MidButton使用OR运算符的组合。具体见下表,读者可自行写出其示例程序,并验证。


以下函数为与鼠标光标位置有关的函数,有关这些位置之间的坐标转换位于QWidget类中④、int x() const; int y() const; //返回鼠标光标的x和y位置。相对于产生事件的部件⑤、QPoint pos() const; //返回鼠标光标的位置。相对于产生事件的部件⑥、const QPointF& localPos() const; //返回鼠标光标的位置。相对于产生事件的部件,qt5.0 ⑦、const QPointF& screenPos() const; //返回鼠标光标的位置。相对于显示屏,qt5.0 ⑧、const QPointF& windowPos() const; //qt5.0

返回鼠标光标的位置(相对于产生事件的窗口),第6~8的函数需要注意,他们返回的是const类型的对象,按C++语法,const类型的对象只能调用const类型的成员函数。⑨、int globalX()const; int globalY()const; //返回鼠标光标的全局x和y位置。⑩、QPoint globalPos() const; //返回鼠标光标的全局位置。

示例:鼠标光标的位置

#include<QWidget>

#include<QMouseEvent>

#include<QPushButton>

#include<QObject>

#include <iostream>

using namespace std;

class B:public QObject{public:

bool eventFilter(QObject *watched, QEvent *event){

QMouseEvent *e=(QMouseEvent*)event;

if(e->type()==QEvent::MouseButtonPress){ //是否是鼠标按下事件

cout<<"x="<<e->x()<<endl; //返回值是相对于本例的按钮AAA左上角的。

cout<<"pos="<<e->pos().x()<<endl; //同上

/*注意:localPos()、windowPos()、screenPos()三个函数返回的是const类型的对象,只能调用const类型的成员函数*/

cout<<"local="<<e->localPos().x()<<endl; //同上

cout<<"window="<<e->windowPos().x()<<endl; //返回值是相对于w左上角的

cout<<"screen="<<e->screenPos().x()<<endl; //返回值是相对于屏幕左上角的

cout<<"global="<<e->globalPos().x()<<endl; } //同上,if结束

return 0; //返回0,以把其余事件交还给目标对象处理。

} //eventFilter结束

};

int main(int argc, char *argv[]){

QApplication aa(argc,argv);//在Qt中QApplication或其子类型的对象只能有一个

QWidget w; B mb; QPushButton *pb=new QPushButton(&w);

pb->move(22,22); //使按钮位于相对于w左上角(22,22)处。

pb->setText("AAA"); pb->installEventFilter(&mb); w.resize(333,222);

w.move(50,50); //使窗口部件在相对屏幕左上角(50,50)处显示

w.show(); aa.exec(); return 0; }

6、QWidget类中与鼠标事件有关的函数①、void grabMouse()

捕获鼠标输入,鼠标输入被捕获后,直到调用releaseMouse()函数之前,所有的鼠标事件都由该部件接收,其他部件则无法接收到鼠标事件。只有可见的部件才能捕获鼠标输入,若isVisible()返回false,则该部件不能调用grabMouse()函数。使用Qt时,通常不需要捕获鼠标,因为Qt会抓住并释放鼠标,特别地,当鼠标按钮被按下时,Qt会捕获鼠标,并将其保持到最后一个按钮被释放为止。

②、void grabMouse(const QCursor &cursor) //捕获鼠标输入,并改变光标的形状。

③、void releaseMouse() //释放捕获的鼠标

④、static QWidget* mouseGrabber(); 返回正在捕获鼠标输入的部件,若没有则返回0。

⑤、bool hasMouseTracking() const;

返回true表示启用了鼠标跟踪,返回false表示禁用鼠标跟踪(默认值),若禁用了鼠标跟踪,则至少需要按下一个鼠标按钮才会产生鼠标移动事件。若启用了鼠标跟踪,则即使未按下鼠标按钮,也会产生鼠标移动事件。

⑥、void setMouseTracking(bool enable) 设置鼠标跟踪状态

⑦、bool underMouse() const;

若部件位于鼠标光标之下,则返回true,否则返回false。此值在拖放操作期间未正确更新。

示例:捕获鼠标输入

#include <QApplication>

#include<QWidget>

#include<QMouseEvent>

#include<QPushButton>

#include<QObject>

#include <iostream>

using namespace std;

class B:public QObject{public:

bool eventFilter(QObject *watched, QEvent *event){

QMouseEvent *e=(QMouseEvent*)event;

QPushButton* w=(QPushButton*)watched;

if(e->type()==QEvent::MouseButtonPress) {

cout<<"B"<<endl;

/*判断光标是否位于部件之下,注:要使以下语句结果为true,需注释掉main函数中的鼠标捕获代码pb->grabMouse();*/

//if(w->underMouse()) cout<<"under"<<endl;

return 1; } // 返回1,结束对此事件的处理。if结束

return 0;} };

class C:public QObject{public:

bool eventFilter(QObject *watched, QEvent *event){

QMouseEvent *e=(QMouseEvent*)event;

if(e->type()==QEvent::MouseButtonPress){ cout<<"C"<<endl; return 1; }

return 0; } };

class D:public QObject{public:

bool eventFilter(QObject *watched, QEvent *event){

QMouseEvent *e=(QMouseEvent*)event;

if(e->type()==QEvent::MouseButtonPress){cout<<"D"<<endl; return 1; }

return 0;} };

int main(int argc, char *argv[]){

QApplication aa(argc,argv);

QWidget w; B mb; C mc; D md;

QPushButton *pb=new QPushButton(&w); QPushButton *pb1=new QPushButton(&w);

pb->move(22,22); pb->setText("AAA"); pb1->move(99,22); pb1->setText("BBB");

pb->installEventFilter(&mb); pb1->installEventFilter(&mc);

w.installEventFilter(&md);

pb->grabMouse(); /*使按钮AAA捕获鼠标,此时产生的鼠标事件都只会发送给按钮AAA,也就是说其他部件无法获得鼠标事件。*/

//pb->setMouseTracking(true); //鼠标跟踪与鼠标移动事件的关系,请读者自行增加代码进行验证。

w.resize(333,222); w.show(); aa.exec(); return 0; }

运行结果及说明:该程序无论在程序的什么位置点击鼠标,鼠标事件都只会传送给按钮AAA,因此只会输出B

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容