QT如何捕获全局的键盘事件?

QT如何捕获全局的键盘事件?

方法一:继承QApplication类,并重载notify()函数

Qt是用QApplication::notify()函数来分发事件的。想要在任何事件过滤器查看任何事件之前先得到这些事件,重载这个函数是唯一的办法。通常来说事件过滤器更好用一些, 因为不需要去继承QApplication类。而且可以给QApplication对象安装任意个数的事件过滤器,相比之下, notify()函数只有一个。

代码如下:

class MyApplication : public QApplication

{

public:

     MyApplication(int&argc,char **argv);

     bool notify(QObject*, QEvent *);

     void setWindowInstance(MainWindow*wnd);

private:

     MainWindow* window;//保存一个你窗体的指针

};

MyApplication::MyApplication(int &argc,char **argv):

QApplication(argc,argv),window(0)

{

}

void MyApplication::setWindowInstance(MainWindow *wnd)

{

     window = wnd;

}

bool MyApplication::notify(QObject *obj, QEvent *e)

{

     const QMetaObject* objMeta = obj->metaObject();
     QString clName = objMeta->className();

     if((e->type() == QEvent::KeyPress) && (clName != "QLineEdit"))
     {

          if(window)

          {

                QKeyEvent*keyEvent = static_cast<QKeyEvent *>(e);

                window->keyPress(keyEvent);

          }

     }

     return QApplication::notify(obj,e);

}

注:

Qt的事件和Qt中的signal不一样. 后者通常用来"使用"widget, 而前者用来"实现" widget. 比如一个按钮, 我们使用这个按钮的时候, 我们只关心他clicked()的signal, 至于这个按钮如何接收处理鼠标事件,再发射这个信号,我们是不用关心的. 但是如果我们要重载一个按钮的时候,我们就要面对event了. 比如我们可以改变它的行为,在鼠标按键按下的时候(mouse press event) 就触发clicked()的signal而不是通常在释放的( mouse release event)时候.

事件的产生

事件的两种来源:

       一种是系统产生的;通常是window system把从系统得到的消息,比如鼠标按键,键盘按键等, 放入系统的消息队列中. Qt事件循环的时候读取这些事件,转化为QEvent,再依次处理.

       一种是由Qt应用程序程序自身产生的.程序产生事件有两种方式, 一种是调用QApplication::postEvent(). 例如QWidget::update()函数,当需要重新绘制屏幕时,程序调用update()函数,new出来一个paintEvent,调用QApplication::postEvent(),将其放入Qt的消息队列中,等待依次被处理.另一种方式是调用sendEvent()函数. 这时候事件不会放入队列, 而是直接被派发和处理, QWidget::repaint()函数用的就是这种方式.

事件的派发和处理

首先说明Qt中事件过滤器的概念. 事件过滤器是Qt中一个独特的事件处理机制, 功能强大而且使用起来灵活方便. 通过它, 可以让一个对象侦听拦截另外一个对象的事件. 事件过滤器是这样实现的: 在所有Qt对象的基类: QObject中有一个类型为QObjectList的成员变量,名字为eventFilters,当某个QObjec (qobjA)给另一个QObject (qobjB)安装了事件过滤器之后, qobjB会把qobjA的指针保存在eventFilters中.在qobjB处理事件之前,会先去检查eventFilters列表, 如果非空, 就先调用列表中对象的eventFilter()函数.一个对象可以给多个对象安装过滤器. 同样, 一个对象能同时被安装多个过滤器, 在事件到达之后, 这些过滤器以安装次序的反序被调用. 事件过滤器函数( eventFilter() ) 返回值是bool型, 如果返回true, 则表示该事件已经被处理完毕, Qt将直接返回, 进行下一事件的处理; 如果返回false, 事件将接着被送往剩下的事件过滤器或是目标对象进行处理.

Qt中,事件的派发是从QApplication::notify() 开始的, 因为QAppliction也是继承自QObject, 所以先检查QAppliation对象, 如果有事件过滤器安装在qApp上, 先调用这些事件过滤器. 接下来QApplication::notify() 会过滤或合并一些事件(比如失效widget的鼠标事件会被过滤掉, 而同一区域重复的绘图事件会被合并). 之后,事件被送到reciver::event() 处理.

同样, 在reciver::event()中, 先检查有无事件过滤器安装在reciever上. 若有, 则调用之. 接下来,根据QEvent的类型, 调用相应的特定事件处理函数. 一些常见的事件都有特定事件处理函数, 比如:mousePressEvent(), focusOutEvent(),  resizeEvent(),paintEvent(), resizeEvent()等等. 在实际应用中,经常需要重载这些特定事件处理函数在处理事件. 但对于那些不常见的事件, 是没有相对应的特定事件处理函数的. 如果要处理这些事件, 就需要使用别的办法, 比如重载event() 函数, 或是安装事件过滤器.

http://blog.csdn.net/cpeasant_eva/article/details/43160549

猜你喜欢

转载自blog.csdn.net/Think88666/article/details/85042048