4065|1

954

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

你不得不熟悉的qt知识 信号与曹 [复制链接]

qt里面 使用信号与曹的机制取代了消息机制,更安全,免得函数指针乱跑。。我在大牛的博客上看到的文章觉得写得很好,转过来了,感谢原作者 在遇到多信号问题的时候,你是否经常会连接多个槽函数呢?如果你的答案是绝对的,那么你已经Out很久了。多信号连接多个槽,实现不同的槽就在潜意识的加大程序的开销!那么为什么不去链接同一个槽呢? 今天在次写下这篇文章,感觉有些唐突,但是又不得不写!因为信号与槽是Qt里面的最基础而且是最重要的部分,有很多人问过我关于信号与槽的问题,就总结一下。Qt主要包括:Qt基础部分(Qt入门、Qt对话框、Qt窗口、自定义窗口部件)、Qt中级(布局管理、事件处理、二维绘图、容器、数据库、多线程、网络等)、Qt高级(国际化、自定义样式、三维绘图、创建插件、嵌入式编程等)。 信号与槽的连接方式看起来会是这样的: Qt5之前: connect(sender, SIGNAL(signal), receiver, SLOT(slot)); Qt5开始: connect(sender, &Sender::signal, receiver, &Receiver::slot); 前者: sender和receiver是指向QObject的指针,signal和slot是不带参数的函数名。SIGNAL()宏和SLOT()宏会把他们的参数转换成相应的字符串。 后者: (1)编译器,检查信号与槽是否存在,参数类型检查,Q_OBJECT宏是否存在 (2)信号可以和普通函数、类的普通成员函数、lambda函数连接(不在局限于信号和槽函数) (3)参数可以是typedef的或者使用不同的namespace specifier (4)可以允许一些自动类型的转换(即信号和槽函数类型不必完全匹配) 1、一个信号连接一个槽 connect(slider, &QSlider::valueChanged, spin_box, &QSpinBox::setValue); 2、一个信号连接多个槽 connect(slider, &QSlider::valueChanged, spin_box, &QSpinBox::setValue); connect(slider, &QSlider::valueChanged, this, &QWidget::showValue); 3、多个信号连接同一个槽 connect(push_button, &QPushButton::clicked, this, &QWidget::show); connect(tool_button, &QToolButton::clicked, this, &QWidget::show); 4、一个信号连接另一个信号 connect(push_button, &QPushlButton::clicked, this, &QWidget::buttonClicked); 5、断开链接 disconnect(push_button); //断开push_button的所有连接 disconnect(push_button, &QPushButton::clicked, this, &QWidget::show); //断开此信号连接的槽 好了,这些都是最基本的应用。那么多个信号连接同一个槽的时候如何进行区分呢? 方法一: typedef enum{ BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4 }BUTTON; push_button_1->setObjectName(QString::number(BUTTON_1, 10)); push_button_2->setObjectName(QString::number(BUTTON_2, 10)); tool_button_1->setObjectName(QString::number(BUTTON_3, 10)); tool_button_2->setObjectName(QString::number(BUTTON_4, 10)); connect(push_button_1, &QPushButton::clicked, this, &MyWidget::changeButton); connect(push_button_2, &QPushButton::clicked, this, &MyWidget::changeButton); connect(tool_button_1, &QToolButton::clicked, this, &MyWidget::changeButton); connect(tool_button_2, &QToolButton::clicked, this, &MyWidget::changeButton); void MyWidget::changeButton() { QObject *object = QObject::sender(); QPushButton *push_button = qobject_cast(object); QToolButton *tool_button = qobject_cast<QToolButton *>(object); int index; if(push_button) { QString object_name = push_button->objectName(); index = object_name.toInt(); } else if(tool_button ) { QString object_name = tool_button->objectName(); index = object_name.toInt(); } QString information = QString(""); switch(index) { case BUTTON_1: information = QString("clicked 1"); break; case BUTTON_2: information = QString("clicked 2"); break; case BUTTON_3: information = QString("clicked 3"); break; case BUTTON_4: information = QString("clicked 4"); break; default: information = QString("which is clicked?"); break; } QMessageBox::information(NULL, QString("Title"), information); } 当然,setObjectName不是专门用来干这事的,也可以使用text进行区分或者其它方法,这里介绍的只是一种思路而已! 方法二: QSignalMapper类可以简单的理解为信号的翻译和转发器, 它可以把一个无参数的信号翻译成带int参数、QString参数、QObject*参数或者QWidget*参数的信号,并将之转发。 QSignalMapper *signal_mapper = new QSignalMapper(this); connect(push_button_1, &QPushButton::clicked, signal_mapper, &QSignalMapper::map); connect(push_button_2, &QPushButton::clicked, signal_mapper, &QSignalMapper::map); connect(tool_button_1, &QToolButton::clicked, signal_mapper, &QSignalMapper::map); connect(tool_button_2, &QToolButton::clicked, signal_mapper, &QSignalMapper::map); signal_mapper->setMapping(push_button_1, QString::number(BUTTON_1, 10)); signal_mapper->setMapping(push_button_2, QString::number(BUTTON_2, 10)); signal_mapper->setMapping(tool_button_1, QString::number(BUTTON_3, 10)); signal_mapper->setMapping(tool_button_2, QString::number(BUTTON_4, 10)); connect(signal_mapper, &QSignalMapper::mapped, this, &MyWidget::changeButton); void MyWidget::changeButton(QString text) { int index = text.toInt(); QString information = QString(""); switch(index) { case BUTTON_1: information = QString("clicked 1"); break; case BUTTON_2: information = QString("clicked 2"); break; case BUTTON_3: information = QString("clicked 3"); break; case BUTTON_4: information = QString("clicked 4"); break; default: information = QString("which is clicked?"); break; } QMessageBox::information(NULL, QString("Title"), information); } 执行顺序 同一信号连接多个槽呢,槽函数执行没有绝对的先后顺序。 如: connect(slider, &QSlider::valueChanged, spin_box, &QSpinBox::setValue); connect(slider, &QSlider::valueChanged, this, &QWidget::showValue); 在Qt5之前,并不是setValue一定会比showValue先执行。 但在Qt5中,文档中这样介绍: A signal can be connected to many slots and signals. Many signals can be connected to one slot. If a signal is connected to several slots, the slots are activated in the same order in which the connections were made, when the signal is emitted.(一个信号连接多个槽,信号发射后,会按照链接顺序执行)。 经过简单测试的确如此:
重载函数连接: 关于QSpinBox的信号:
自定义槽函数:
connect(spin_box, &QSpinBox::valueChanged, this, &ListView::changeValue); 信号与槽连接看上去很正确,但是会出现如下错误: 意思就是说不能够明确的找出到底调用的是哪个信号(因为只有函数名称,并无详细参数说明),所以需加上参数说明,调用static_cast进行转换。 connect(spin_box, static_cast(&QSpinBox::valueChanged), this, &ListView::changeValue); 总结就到这里,都是很常用的东西,编程过程中多注意细节部分,多总结就好了。很多东西文档里都说的很清楚,write less,do more。。。 注: 技术在于交流、沟通,转载请注明出处并保持作品的完整性。 作者:╰☆奋斗ing❤孩子` 原文:http://blog.sina.com.cn/s/blog_a6fb6cc90101epbg.html

最新回复

mark  详情 回复 发表于 2014-11-11 15:08
点赞 关注

回复
举报

23

帖子

4

TA的资源

一粒金砂(初级)

沙发
 
mark
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表