QT中信号和槽机制

1.自定义槽函数

在实际应用中,由于处理的业务逻辑因应用而定,所以大多数时候需要程序员自定义实现相应的业务逻辑。

2.自定义信号

在实际应用中,用户的操作所触发的信号可以穷举,这些操作所产生的大部分信号QT已经写好了,所以大多数时候不需要我们自定义信号。
自定义信号操作步骤:
1)在对应类中加入signals关键字。
2)定义自定义信号,注意自定义信号函数返回值必须是void,有没有参数都可以,甚至可以支持函数重载。
3)编写自定义信号对应的槽函数,并使用connect关联槽函数和信号。
4)在需要触发信号的地方使用emit触发自定义信号。(在QT5中不使用emit,直接在对应位置调用信号函数也可以实现发送信号,但是建议还是使用emit,这样可以提高可读性)


在这里插入图片描述

图1. emit触发自定义信号

3.带参数的信号槽

信号和槽也可以带参数,注意:当信号带有参数的时候,槽的参数必须和信号的参数一致(这里的一致主要是指参数类型一致,个数如果不一致也可以。个数不一致时,要求信号的参数个数要比槽函数的参数个数更多)。当发射信号的时候,就可以给信号函数传递实参,与之对应的这个参数就会被传递到对应的槽函数中。此时就可以起到信号给槽传参的效果。

在这里插入图片描述

图2. emit触发自定义信号传参给槽函数
使用带参数的信号槽,可以通过一套信号槽搭配不同的参数,来实现代码的复用。比如使用多个按钮来切换页面不同的标题,每个按钮对应一个页面标题,这种情况下就可以通过自定义一个带参数的信号槽来实现。而不需要通过定义多个信号槽。QT中很多内置信号也是带有参数的,只不过这些参数不需要我们自己去传递,比如:clicked(bool)
思考:为什么允许信号的参数可以比槽的参数多?
因为如果我们严格要求参数个数一致,这就意味着信号绑定到槽的要求就变高了。在参数个数可以不一致这样的规则下,就允许信号和槽之间的绑定更灵活了。就可以让多个信号(多个参数不同的信号)绑定到一个槽上面。当参数个数不一致时,槽函数就会按照参数顺序,拿到信号的前N个参数,并且确保前N个参数的类型与槽函数的参数类型一致。这样至少需要确保槽函数的每个参数都是有值的。即要求信号给槽的参数可以有富裕,但是不能少。
注意:自己在QT中编写的类如果要使用到信号和槽必须在类中包含Q_OBJECT这个宏。

4.信号和槽存在的意义

信号和槽是为了解决响应用户操作的问题,它在GUI开发的各种框架中是一个比较有特色的存在。在其他的GUI开发框架中搞的方式都要简洁一些。在网页开发中响应用户操作主要就是挂回调函数,挂回调函数的方式比较简单,处理函数就像控件的一个属性/成员一样(如下面代码所示),就不需要搞一个单独的connect完成上述的信号和槽的连接。大部分的GUI开发框架也都是这么搞的。
button.onclick = handle;
function handle()
{
	......
}

QT中信号和槽connect这种机制有很美好的设想。
1)解耦合:实现了触发用户操作的控件和处理对应用户的逻辑操作之间的解耦合。
2)实现“多对多”效果:一个信号可以连接到多个槽函数上,一个槽函数也可以被多个槽函数connect

5.信号和槽断开连接

使用disconnect来断开信号和槽的连接,disconnect与connect的使用非常类似。disconnect的使用比较少见,大部分情况下,把信号和槽连上之后就不用管了。主动断开的情况往往是打算把信号重新绑定到另一个槽函数上。在这种情况下如果不disconnect就会出现一个信号绑定多个槽函数的情况

在这里插入图片描述

图3. 一个信号触发槽函数后在槽函数中解绑并重新绑定槽函数

在这里插入图片描述

图4. 一个信号触发槽函数后在槽函数中不解绑并重新绑定槽函数

可以看到重新connect绑定一个信号到槽函数,如果不disconnect解绑原来的槽函数,该信号会同时触发多个槽函数。

6.使用lambda表达式定义槽函数

注意在lambda表达式内部如果需要用到外面的变量需要在[]中列出,多个变量之间用逗号(,)隔开,需要所有外部变量时可以用等号替代,即[=]。 当访问外部变量属于某个类的私有变量时,只有通过this指针进行访问,即[this],而不能使用[variate],否则会报错。

在这里插入图片描述

图5. lambda表达式访问类内成员报错

在这里插入图片描述

图6. lambda表达式通过this指针访问类内成员

如果槽函数比较简单,而且是一次性使用就会使用lambda表达式来定义槽函数。此外还需要确认捕获到lambda内部的变量是有意义的,因为回调函数执行的时机是不确定的(用户啥时候点击按钮不知道),要保证无论何时用户点击了按钮,捕获到的变量都能正确使用。如果在使用之前捕获到的变量被释放了是不行的。
lambda表达式是C++11中引入的,对于QT5及以上版本默认是按照C++11来编译的。如果使用QT4或者更老的版本需要在.pro文件中加上C++11的编译选项(CONFIG += c++11)。
  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值