2.3信号和槽(上)
如果面试官问你Qt最明显区别于其它开发框架的特征是什么 , 那么你的回答一定是信号和槽 , 为此 , 小豆君将拿出三节的时间来讲述信号和槽 。
本节只讲解非线程间的信号槽 , 等后面学习的深入 , 再讲解线程间信号槽通信 。
第一节 , 信号槽的基本概念 。
第二节 , 信号槽的扩展知识 。
第三节 , 分析Qt的moc与编译器生成的moc源文件 , 帮助大家理解信号槽的来龙去脉 。
2.3.1 引子在面向对象的编程方法中 , 都会创建很多的实例 , 每个实例都是单独的 , 要想每个实例能够协同合作 , 那么就会需要一种对象间传递消息的机制 , 在很多框架中都采用回调函数来进行对象间信息传递 。
回调是一个指向函数的指针 , 如果想要一个处理函数通知一些事件 , 你需要将这个指针传递给处理函数 。 处理函数在适当时间调用回调函数 。 MFC就是使用的回调函数 , 但回调可能是不直观的 , 不易于理解的 , 并且也不能保证是类型安全的 。
Qt为了消除回调函数等的弊端 , 从而开发了一种新的消息传递机制 , 即信号和槽 。
例如 , 当我们要求鼠标点击某个按钮时 , 对应的窗口就需要关闭 , 那么这个按钮就会发出一个点击信号 , 而窗口接收到这个信号后执行关闭窗口 。 那么 , 这个信号就是按钮被点击 , 而槽就是窗口执行关闭函数 。
可以将信号和槽理解成“命令-执行” , 即信号就是命令 , 槽就是执行命令 。
文章插图
2.3.2 信号【2.3信号和槽(上)】当一个对象的内部状态发生改变时 , 如果其它对象对它的状态需要有所反应 , 这时就应该让这个类发出状态改变的信号 。
声明信号使用signals关键字
发送信号使用emit关键字
注意:
1.所有的信号声明都是公共的 , 所以Qt规定不能在signals前面加public,private, protected 。 2.所有的信号都没有返回值 , 所以返回值都用void 。 3.所有的信号都不需要定义 。 4.必须直接或间接继承自QOBject类 , 并且开头私有声明包含Q_OBJECT 。 5.当一个信号发出时 , 会立即执行其槽函数 , 等待槽函数执行完毕后 , 才会执行后面的代码 , 如果一个信号链接了多个槽 , 那么会等所有的槽函数执行完毕后才执行后面的代码 , 槽函数的执行顺序是按照它们链接时的顺序执行的 。 6.在链接信号和槽时 , 可以设置链接方式为:在发出信号后 , 不需要等待槽函数执行完 , 而是直接执行后面的代码 。 7.发出信号使用emit关键字 。 8.信号参数的个数不得少于槽参数的个数 。
2.2.3 槽槽其实就是普通的C++函数 , 它唯一特点就是能和信号链接 。 当和它链接的信号被发出时 , 这个槽就会被调用 。
声明槽可以使用:public/protected/private slots:
以上是Qt4的做法 , 在Qt5中你也不需要使用这些声明 , 每个函数都可以被当作是槽函数 , 而且还可以使用Lambda表达式来作为槽 。 不过为了程序的可读性 , 我还是推荐槽函数要声明一下 。
2.2.4连接信号和槽使用connect函数连接信号和槽
2.2.4.1 原型1static QMetaObject::Connection connect(const QObject *sender, //信号发送对象指针const char *signal,//信号函数字符串 , 使用SIGNAL()const QObject *receiver, //槽函数对象指针const char *member, //槽函数字符串 , 使用SLOT()Qt::ConnectionType = Qt::AutoConnection//连接类型 , 一般默认即可);//例如connect(pushButton, SIGNAL(clicked()), dialog,SLOT(close()));
Qt4和Qt5都可以使用这种连接方式
2.2.4.2 原型2static QMetaObject::Connection connect(const QObject *sender, //信号发送对象指针const QMetaMethod //例如connect(pushButton, QPushButton::clicked, dialog,QDialog::close);
Qt5新增这种连接方式 , 这使得在编译期间就可以进行拼写检查 , 参数检查 , 类型检查 , 并且支持相容参数的兼容性转换 。
2.2.5 信号槽示例新建窗口项目SignalsAndSlotsWidget , 类名同为SignalsAndSlotsWidget , 基类选择QWidget 。
在ui中拖入1个QLineEdit , 1个QLable , 1个QSlider , 如下图
文章插图
头文件
class SignalsAndSlotsWidget : public QWidget{Q_OBJECTpublic:explicit SignalsAndSlotsWidget(QWidget *parent = 0);~SignalsAndSlotsWidget();signals://自定义信号 , 发出此信号 , 使得QLabel显示文字void sigShowVal(const QStringpublic slots://自定义槽 , 当LineEdit发出文字改变的信号时 , 执行这个槽void sltLineEditChanged(const QStringprivate:Ui::SignalsAndSlotsWidget *ui;};
- OPPO|OPPO未来科技大会正式官宣,官方明示将有旗舰新品和创新技术亮相
- 运营商|信号走丢的锅该谁背?运营商:咱中国人别坑中国人……
- 小米科技|雷军:小米12即将发布!首款搭载骁龙8手机,性能和功耗咋样?
- 支付宝|突破2项关键技术,中科院又立功了,事关量子计算和3D打印
- |联想小新air和pro的区别大吗?哪个性能更强?详细解读
- |LoRa做到了!实现低功耗和远距离通信!
- 监管机构|谷歌和Meta被俄罗斯监管机构告上法庭,或面临巨额罚款
- 革命|MicroLED和QD-OLED都有了,三星下一代显示技术会“忽视”激光显示吗
- oppo reno|OPPO Reno7和vivo S10哪款好?多方位对比给你答案
- 倪光南|一个伟大的院士和真正的股东被欺负到扫地出门地步,公理何在?