Qt中的事件处理

引入

事件不是信号与槽;
这两个概念很容易混淆,究其本质信号与槽其实是Qt用来处理事件的一种处理机制,我们不能把它混为一谈。

其实还有很多不同的事件处理机制的,例如js使用的事件绑定机制,windows采用的消息机制,详情大家可以看我另外几篇博客windows消息机制学习

事件是什么?

事件就是一件事情,或者说是一个操作行为,用户移动鼠标、点击鼠标、敲击键盘等等所有的操作都称为事件(系统也可以发出事件,如计时器事件等)

事件的具体实现方式

事件的实现是通过订阅发布模式实现的,即在代码运行中预先定义事件,在后面某个操作中触发这个预先定义好的事件,执行事件处理程序(具体的源码大家可以看看windows的官方文档

在Qt中我们处理事件采用的链式处理,和浏览器的DOM2事件模型一致,共有三个过程:

  1. 事件捕获阶段(自上而下)
    捕获指的是事件从Windows对象一直向下传播到目标元素,依次检查经过的节点是否绑定了事件监听函数,如果有则执行,不然
  2. 处于目标阶段
    又称事件处理阶段,这个阶段执行目标元素绑定的监听事件
  3. 事件冒泡阶段(自下而上)
    冒泡指的是事件从目标元素冒泡到Windows对象,依次检查经过的节点是否绑定了事件监听函数

为啥事件都处理还要再冒泡呢?我们来看一个代码就明白了!

void MyLabel::mousePressEvent(QMouseEvent * event)
{
        if(event->button() == Qt::LeftButton) {
                // do something
        } else {
                QLabel::mousePressEvent(event);
        }
}

我们在子类中重写了事件函数,在鼠标按下的事件中检测,如果按下的是左键,做我们的处理工作,如果不是左键,则调用父类的函数,这可以说事件向上传递给父类去响应,也就是我们在子类中忽略了这个事件导致事件必须冒泡

我们可以把Qt的事件传递看成责任链结构,如果在事件捕获阶段子类没有找到事件处理函数,就会继续向其他类传递

(其实,Qt的事件对象都有一个 accept()函数和 ignore()函数。正如它们的名字,前者用来告诉 Qt,事件处理函数“接收”了这个事件,不要再传递;后者则告诉 Qt,事件处理函数“忽略”了这个事件,需要继续传递,寻找另外的接受者。在事件处理函数中,可以使用 isAccepted()来查询这个事件是不是已经被接收了)

我们很少使用 accept()和 ignore()函数,而是想上面的示例一样,如果希望忽略事件,只要调用父类的响应函数即可。记得我们曾经说过,Qt 中的事件大部分是 protected 的,因此,重写的函数必定存在着其父类中的响应函数,这个方法是可行的。为什么要这么做呢?因为我们无法确认父类中的这个处理函数没有操作,如果我们在子类中直接忽略事件,Qt 不会再去寻找其他的接受者,那么父类的操作也就不能进行,这可能会有潜在的危险。

但是有一个情景下,我们也必须使用accept()和ignore()函数,就是在窗口关闭的时候,你想有个询问对话框就必须要主动使用accept()函数去主动接受这个消息(也可以把他想成一种Hook机制,它将发送给QObject的消息给主动拦截下来了,用来处理自己的工作)

void MainWindow::closeEvent(QCloseEvent * event)
{
        if(continueToClose()) {
                event->accept();
        } else {
                event->ignore();
        }
}

bool MainWindow::continueToClose()
{
        if(QMessageBox::question(this,
                                            tr("退出"),
                                            tr("你确定要关闭窗口吗?"),
                                            QMessageBox::Yes | QMessageBox::No,
                                            QMessageBox::No)
                == QMessageBox::Yes) {
                return true;
        } else {
                return false;
        }
}

参考

我们还可以站在网页编程的角度来定义事件:
事件是什么?事件模型?

浏览器还可以直接处理DOM0事件,Qt因为存在Windows类和Qtapplication类的交互的问题,我还不知道能不能直接在Qt窗口的DOM内直接写事件处理函数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AlbertOS

还会有大爷会打钱?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值