QT之鼠标事件的全局捕获

Qt的事件模型一个强大的功能是一个QObject对象能够监视发送其他QObject对象的事件,在事件到达之前对其进行处理。
QT之鼠标事件的全局捕获_第1张图片

上示的图片黑色键盘是一个独立的Widget的子类CKeyboardForm,白色的背景部分是一个独立的主窗口。现在要实现在白色背景上任意点击某一位置即可实现虚拟键盘的收起,很显然这里就要通过CKeyboardForm来截取全局的鼠标(触摸屏)点击事件,并在代码的监视处实现以上的功能,这就是事件过滤的方法。实现一个事件的过滤包括两个步骤
1.在目标对象上调用installEventFilter(),注册监视对象。
2.在监视对象的EventFilter()函数中处理目标对象的事件。
注册监视对象的位置是在CKeyboardForm的构造函数当中:CKeyboardForm::CKeyboardForm(QWidget parent)
: QWidget(parent)
{
m_lstCharacterBtn.clear();
m_eCurrentMode = InputMode::en;
m_bUpperMode = false;
m_iSymbolPage = 0;
QDesktopWidget
desktopWidget = QApplication::desktop();

//global capture
qApp->installEventFilter(this);
}

事件过滤器注册之后,发送到qApp的事件首先到达CKeyboardForm::eventFilter()函数,然后在到达最终的目的地。
下面是eventFilter()的代码。
bool CKeyboardForm::eventFilter(QObject *watched, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = dynamic_cast(event);
if(mouseEvent->buttons() == Qt::LeftButton)
{
QPoint pos = mouseEvent->globalPos();

if(pos.y() <= 450)
{
//qDebug()<<“x=”< emit clicked_tran();
}

}
}

return QWidget::eventFilter(watched, event);
}
如果事件是鼠标事件的话,把Event转换成MouseButtonPress,当确定了鼠标点击后,或者当下鼠标点击位置的绝对坐标,然后通过绝对坐标的纵坐标判断是否激发相关信号。
/
Qt 的事件处理有5中级别:

  1. 重写控件的事件处理函数:如重写keyPressEvent(),mousePressEvent()和paintEvent(),这是最常用的事件处理方法,我们已经看到过很多这样的例子了。
  2. 重写QObject::event(),在事件到达事件处理函数时处理它。在需要改变Tab键的惯用法时这样做。也可以处理那些没有特定事件处理函数的比较少见的事件类型(例如,QEvent::HoverEnter)。我们重写event()时,必须要调用基类的event(),由基类处理我们不需要处理的那些情况。
  3. 给QObject对象安装事件过滤器:对象用installEventFilter()后,所有达到目标控件的事件都首先到达监视对象的eventFilter()函数。如果一个对象有多个事件过滤器,过滤器按顺序激活,先到达最近安装的监视对象,最后到达最先安装的监视对象。
  4. 给QApplication安装事件过滤器,如果qApp(唯一的QApplication对象)安装了事件过滤器,程序中所有对象的事件都要送到eventFilter()函数中。这个方法在调试的时候非常有用,在处理非活动状态控件的鼠标事件时这个方法也很常用。
  5. 继承QApplication,重写notify()。Qt调用QApplication::nofity()来发送事件。重写这个函数是在其他事件过滤器处理事件前得到所有事件的唯一方法。通常事件过滤器是最有用的,因为在同一时间,可以有任意数量的事件过滤器,但是notify()函数只有一个。
    许多事件类型,包括鼠标,键盘事件,是能够传播的。如果事件在到达目标对象的途中或者由目标对象处理掉,事件处理的过程会重新开始,不同的是这时的目标对象是原目标对象的父控件。这样从父控件再到父控件,知道有控件处理这个事件或者到达了最顶级的那个控件。
    下图显示了一个键盘事件在一个对话框中从子控件到父控件的传播过程。当用户敲击一个键盘,时间首先发送到有焦点的控件上(这个例子中是QCheckBox)。如果QCheckBox没有处理这个事件,Qt把事件发送到QGroupBox中,如果仍然没有处理,则最后发送到QDialog中。
    QT之鼠标事件的全局捕获_第2张图片


上诉例子说明的是第四种情况(给QApplication安装事件过滤器),下面给出第五种情况(继承QApplication,重写notify())的伪代码,一起学习。

//.h文件

#ifndef MYQAPPLICATION_H
#define MYQAPPLICATION_H

#include
#include

class CMyApplication : public QApplication
{
Q_OBJECT

public:
CMyApplication(int &argc, char **argv);
~CMyApplication();

bool notify(QObject *, QEvent *);

};
#endif

//.cpp文件
#include “MyQApplication.h”
#include

CMyApplication::CMyApplication(int &argc, char **argv):QApplication(argc,argv)
{

}

CMyApplication::~CMyApplication()
{

}

bool CMyApplication::notify(QObject *obj, QEvent *e)
{
const QMetaObject *objMeta = obj->metaObject();
QString clName = objMeta->className();

if(e->type() == QEvent::MouseButtonPress)
{
    QMouseEvent *mouseEvent = static_cast(e);
    if(mouseEvent->buttons() == Qt::LeftButton)
    {
        qDebug()<<"left"<

}

//main函数
#include
#include
#include “myapplication.h”
int main(int argc, char *argv[])
{
//注意此处是用myApplication构造不是QApplication
myApplication a(argc, argv);

QWidget  w;
w.show();

return a.exec();

}

你可能感兴趣的:(QT,qt)