当前位置: 首页 > news >正文

使用 C++11 Lambda 表达式在 Qt 中连接信号与槽

在 Qt 使用 C++11 引入的 lambda 表达式来简化信号与槽的连接已经成为一种不错的选择。本文将通过一个简单的例子来展示如何使用 lambda 表达式来连接 QAction 的信号与槽。

传统的连接方式

首先,看看传统的连接方式:

QAction* action = foo->addAction(tr("Some Action"));
connect(action, SIGNAL(triggered()), this, SLOT(onSomeAction()));

这里,我们使用了经典的 connect 方法来连接 QActiontriggered() 信号到 onSomeAction 槽函数。onSomeAction 的实现如下:

void MyClass::onSomeAction()
{QAction* caller = qobject_cast<QAction*>(sender());Q_ASSERT(caller != nullptr);// 对 caller 进行一些操作
}

这种方式能够正常工作,我们可以获取到触发这个槽函数的 QAction 对象,并进行相关操作。

使用 C++11 Lambda 表达式来连接

现在我们使用 C++11 的 lambda 表达式来重写连接代码:

connect(action, &QAction::triggered, [this]()
{QAction* caller = qobject_cast<QAction*>(sender());Q_ASSERT(caller != nullptr);// 对 caller 进行一些操作
});

常见错误及解决方法

当你尝试使用 lambda 表达式时,可能会遇到 caller 总是 nullptr 的情况,导致 Q_ASSERT 触发。这是因为使用 lambda 表达式时不需要再调用 sender() 函数,而是应该直接捕获 action 对象。

connect(action, &QAction::triggered, this, [action, this]() {// 直接使用 action 对象Q_UNUSED(action); // 如果不使用 action,可避免编译器警告// 执行你的操作
});

通过捕获 action 对象,可以避免使用 sender() 和可能出现的空指针问题。

进一步优化

以下是一些连接信号和槽时需要注意的事项,以避免悬挂指针(dangling pointer)的问题:

  1. 在捕获变量时按值捕获源对象和目标对象。例如:

    connect(a, &A::foo, b, [a, b]() {// 使用 a 和 b
    });
    
  2. 在跨线程的情况下,需要特别注意对象的生命周期。在函数对象被调用时,不能保证所捕获的指针仍然有效。

总结

使用 C++11 的 lambda 表达式可以让 Qt 的信号与槽连接更加简洁。但是在使用时一定要注意对象的生命周期和指针的有效性。以下是一个更完整的示例,展示如何在主函数中使用 lambda 表达式来连接信号与槽:

int main(int argc, char *argv[])
{QApplication a(argc, argv);QLabel lbl{"Hello World!"};QPushButton btn;btn.show();lbl.show();QObject::connect(&btn, &QPushButton::clicked, [&lbl]{lbl.setText("Button clicked");});return a.exec();
}

相关文章:

  • MySQL中的系统变量权限
  • 字节跳动:从梦想之芽到参天大树
  • 二叉树经典OJ练习
  • Webfunny【用户细查】七项功能升级更新:大幅提升用户排查效率!
  • CLIP-ReID代码解读七——model.py上
  • gitee添加别人的仓库后,在该仓库里添加文件夹/文件
  • 协程执行顺序引发的问题
  • 如何配置taro
  • C++STL 初阶(5)vector的简易实现(上)
  • [MRCTF2020]PixelShooter
  • Jenkins+K8s实现持续集成(一)
  • 晶谷电子器件烧结封装介质材料 绝缘用晶谷低温封接环保玻璃粉 耐压高
  • git stash Pop 后丢失,要如何找回?
  • python输入、输出和变量
  • Java——集合(一)
  • php的引用
  • 2017 年终总结 —— 在路上
  • C++入门教程(10):for 语句
  • Codepen 每日精选(2018-3-25)
  • EOS是什么
  • ESLint简单操作
  • es的写入过程
  • HTTP--网络协议分层,http历史(二)
  • log4j2输出到kafka
  • React-redux的原理以及使用
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • use Google search engine
  • web标准化(下)
  • windows下如何用phpstorm同步测试服务器
  • 前端相关框架总和
  • 使用agvtool更改app version/build
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 想写好前端,先练好内功
  • 在weex里面使用chart图表
  • Android开发者必备:推荐一款助力开发的开源APP
  • 通过调用文摘列表API获取文摘
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • # linux从入门到精通(三)
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #define,static,const,三种常量的区别
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • $refs 、$nextTic、动态组件、name的使用
  • (3)nginx 配置(nginx.conf)
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (强烈推荐)移动端音视频从零到上手(下)
  • (一)RocketMQ初步认识
  • (转)视频码率,帧率和分辨率的联系与区别
  • (转载)(官方)UE4--图像编程----着色器开发
  • (自用)gtest单元测试
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .DFS.