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