installEventFilter可以安装到任何QObject的子类,并不仅仅是UI组件。事件过滤器和安装过滤器的组件必须在同一线程,在它们分属在不同线程时,事件过滤器也是不起作用的
Posted findumars
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了installEventFilter可以安装到任何QObject的子类,并不仅仅是UI组件。事件过滤器和安装过滤器的组件必须在同一线程,在它们分属在不同线程时,事件过滤器也是不起作用的相关的知识,希望对你有一定的参考价值。
Qt的事件知识点:
①事件对象创建完毕后,Qt 将这个事件对象传递给 QObject 的 event() 函数。event() 函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。
②event() 函数主要用于事件的分发。
③事件过滤例子:
解释这个例子之前先看:bool eventFilter(QObject*obj,QEvent*event); [virtual]
注意: eventFilter 函数返回 bool 值,
即, 如果你要自己处理事件, 并且“吞掉”事件,阻止父类对事件的继续处理, 就返回 true; 如果需要父类也处理这一事件,返回 false。通俗点说就是:
它会检查接收到的事件。如果这个事件是我们感兴趣的类型,就进行我们自己的处理;如果不是,就继续转发。
这个函数返回一个 bool 类型,如果你想将参数 event过滤出来,比如,不想让它继续转发,就返回 true,否则返回 false。事件过滤器的调用时间是目标对象(也就是参数里面的 watched对象)接收到事件对象之前。也就是说,如果你在事件过滤器中停止了某个事件,那么,watched对象以及以后所有的事件过滤器根本不会知道这么一个事件。
那么上面的例子的意思就是:
MainWindow是我们定义的一个类,这个类里面会定义许多不同的组件,比如texEdit,我们就是使用MainWindow的eventFilter()函数对它上面的组件进行过滤事件。我们重写了它的 eventFilter()函数。为了过滤特定组件上的事件,首先需要判断这个对象是不是我们感兴趣的组件,然后判断这个事件的类型。在上面的代码中,我们不想让textEdit组件处理键盘按下的事件。所以,首先我们找到这个组件,如果这个事件是键盘事件,则直接返回 true,也就是过滤掉了这个事件,其他事件还是要继续处理,所以返回 false。对于其它的组件,我们并不保证是不是还有过滤器,于是最保险的办法是调用父类的函数。
当返回true是textEdit组件内部是不能用键盘输入字符的,但是可以粘贴,这说明是被过滤掉了,但是返回false是就可以用键盘输入字符。
④voidQObject::installEventFilter(QObject* filterObj )
这个函数是QObject的一个函数,因此可以安装到任何QObject的子类,并不仅仅是UI组件。这个函数接收一个QObject对象,调用了这个函数安装事件过滤器的组件会调用filterObj定义的eventFilter()函数。例如,textField.installEventFilter(obj),则如果有事件发送到textField组件是,会先调用obj->eventFilter()函数,然后才会调用textField.event()。
我们可以向一个对象上面安装多个事件处理器,只要调用多次 installEventFilter()函数。如果一个对象存在多个事件过滤器,那么,最后一个安装的会第一个执行,也就是后进先执行的顺序。一般这个函数的调用时在构造函数里面:
⑤如果你在事件过滤器中 delete了某个接收组件,务必将函数返回值设为 true。否则,Qt还是会将事件分发给这个接收组件,从而导致程序崩溃。
事件过滤器和被安装过滤器的组件必须在同一线程,否则,过滤器将不起作用。另外,如果在安装过滤器之后,这两个组件到了不同的线程,那么,只有等到二者重新回到同一线程的时候过滤器才会有效。(大牛解释是:事件过滤器和安装过滤器的组件必须在同一线程。Qt 里面,对象创建之后,可以使用 moveToThread() 函数将一个对象移动到另外的线程。在这种情形下(当然,事件过滤器必须在同一线程时才能被正确安装,这是第一句话说明的),在它们分属在不同线程时,事件过滤器也是不起作用的,只用当它们重新回到同一线程(使用 moveToThread() 或者是线程自然结束)时,过滤器才能重新工作。)
⑥如果使用 installEventFilter() 函数给一个对象安装事件过滤器,那么该事件过滤器只对该对象有效,只有这个对象的事件需要先传递给事件过滤器的 eventFilter() 函数进行过滤,其它对象不受影响。
⑦如果给 QApplication 对象安装事件过滤器,那么该过滤器对程序中的每一个对象都有效,任何对象的事件都是先传给 eventFilter() 函数而且第一个获得该事件。
⑧事件的分发既可以是同步的,又可以是异步的,而函数的调用或者说是槽的回调总是同步的。事件的另外一个好处是,它可以使用过滤器。
⑨
void QObject::installEventFilter(QObject * filterObj)
Installs an event filter filterObj on this object. For example:
An event filter is an object that receives all events that are sent to this object. The filter can either stop the event or forward it to this object. The event filter filterObj receives events via its eventFilter() function. TheeventFilter() function must return true if the event should be filtered, (i.e. stopped); otherwise it must return false.
If multiple event filters are installed on a single object, the filter that was installed last is activated first.
Here‘s a KeyPressEater class that eats the key presses of its monitored objects:
And here‘s how to install it on two widgets:
The QShortcut class, for example, uses this technique to intercept shortcut key presses.
Warning: If you delete the receiver object in your eventFilter() function, be sure to return true. If you return false, Qt sends the event to the deleted object and the program will crash.
Note that the filtering object must be in the same thread as this object. IffilterObj is in a different thread, this function does nothing. If either filterObjor this object are moved to a different thread after calling this function, the event filter will not be called until both objects have the same thread affinity again (it is not removed).
---------------------
作者:helmsgao
来源:CSDN
原文:https://blog.csdn.net/love_gaohz/article/details/10496631
版权声明:本文为博主原创文章,转载请附上博文链接!
以上是关于installEventFilter可以安装到任何QObject的子类,并不仅仅是UI组件。事件过滤器和安装过滤器的组件必须在同一线程,在它们分属在不同线程时,事件过滤器也是不起作用的的主要内容,如果未能解决你的问题,请参考以下文章
QT Linux平台屏蔽按键事件(installEventFilter使用) 自定义拦截按键输入