可以先看我这个博客 就能知根知底了:qt源码解析1--事件循环原理(重写事件函数,事件过滤器等)
- 用户键盘或者鼠标输入
- 操作系统内核检测到,把这些事件放进一个缓冲队列里,唤醒qt事件循环派发函数。
- qt应用程序的事件循环派发函数循环的的检查这个缓冲队列里是否还有未处理完的事件
- 检测到了还有事件,则判断该事件产生的屏幕坐标,发送给对应的窗口部件
- 每个窗口部件都是继承于QObject类,这个类里就包含了事件处理相关(QEvent类)的虚函数(鼠标按下,鼠标释放等等),然后调用这些虚函数(很多虚函数默认是会调用一个钩子函数的,这就是信号发射)
- 根据C++虚函数原理,子类重写的这些事件处理虚函数,会得到真正的执行了。
qt事件处理相关需要注意的:
- 重写事件处理函数时候,需要在后面调用一下父类的事件处理函数,这样才能实现事件默认处理功能
- qt发送事件给部件时,只发送给那个焦点部件,如果我们还想让它能继续发送给父窗口部件(注:这里是父窗口部件,不是父类),那么调用一下ignore()函数。
void MyLineEdit::keyPressEvent(QKeyEvent *event) // 键盘按下事件
{
qDebug() << tr("MyLineEdit键盘按下事件");
QLineEdit::keyPressEvent(event); // 执行QLineEdit类的默认事件处理
event->ignore(); // 忽略该事件
}
传递过程:
事件先传递给子控件,子控件再传递给父控件(但是这个需要事件函数里返回false,或者调用ignore函数,否则默认是不往父控件传递了,事实上默认就是不继续传递的)。Qt学习之路27--事件传递过程和事件过滤器_一念之间、的博客-CSDN博客
我们可以看出,事件传递方向:子控件 --> 父控件
那么如果说我们实在父控件里面触发的事件,那么如何直接让子控件先接收呢?
这个其实就是给这个父控件安装一个事件过滤器即可,这样子控件的 eventFilter()函数就能优先接收到这个事件(儿子直接抢走老爸的事件),返回值为true,则表示不让事件传递给父控件自己了,否则可以继续传递。当然安装反一下,即使是给儿子的事件,老爸也能先得到事件啦(虽然不安装事件过滤器的话,事件也能最后传到老爸这里)。事件过滤器不仅仅是子对象和父对象之间的使用,任意两个继承QObject的不相关对象都可以使用的。