信号和槽
2015-12-21 16:21
295 查看
1) 信号的定义必须在signals:保留字下,并且不需要实现
2)槽的定义必须在slots:保留字下,需要实现
3)信号和槽通过QObject::connect函数连接
4)当信号被触发时,槽函数被调用
需要注意的是:
1)信号和槽,是QT的拓展,所以实现信号和槽的类,必须是QObject的子类
2)实现信号和槽的类,必须以宏Q_OBJECT开始
3)连接信号和槽,要用到SIGNAL和SLOT宏,转换函数为字符串
4)一个信号可以和多个槽连接,槽函数调用的顺序是不确定的
5)多个信号可以同时连接一个槽
6)信号可以连接信号,形成信号传导
7) 当信号与槽函数的参数数量相同时,它们参数类型要完全一致。
当信号的参数与槽函数的参数数量不同时,只能是信号的参数数量多于槽函数的参数数量,且前面相同数量的参数类型应一致,信号中多余的参数会被忽略。
8)信号和槽都可以重载
9)信号和槽都可以有默认参数
10)槽函数可以像普通函数一样被调用
11)在槽函数中,调用sender可以获得信号调用者
总结下:
一个类:QObject信号和槽都是这个类的子类
三个宏:Q_OBJECT SIGNAL SLOT
三个保留字:signals, slots, emit
在 Qt 5 中,
注意:用lambda表达式在.pro中加入 CONFIG += C++11
QT4我们使用了SIGNAL和SLOT这两个宏,将两个函数名转换成了字符串。注意,即使quit()是QApplication的 static 函数,也必须传入一个对象指针。这也是 Qt 4 的信号槽语法的局限之处。另外,注意到connect()函数的 signal 和 slot 都是接受字符串,因此,不能将全局函数或者 Lambda 表达式传入connect()。一旦出现连接不成功的情况,Qt 4 是没有编译错误的(因为一切都是字符串,编译期是不检查字符串是否匹配),而是在运行时给出错误。这无疑会增加程序的不稳定性。
eg:
2)槽的定义必须在slots:保留字下,需要实现
3)信号和槽通过QObject::connect函数连接
4)当信号被触发时,槽函数被调用
需要注意的是:
1)信号和槽,是QT的拓展,所以实现信号和槽的类,必须是QObject的子类
2)实现信号和槽的类,必须以宏Q_OBJECT开始
3)连接信号和槽,要用到SIGNAL和SLOT宏,转换函数为字符串
4)一个信号可以和多个槽连接,槽函数调用的顺序是不确定的
5)多个信号可以同时连接一个槽
6)信号可以连接信号,形成信号传导
7) 当信号与槽函数的参数数量相同时,它们参数类型要完全一致。
当信号的参数与槽函数的参数数量不同时,只能是信号的参数数量多于槽函数的参数数量,且前面相同数量的参数类型应一致,信号中多余的参数会被忽略。
8)信号和槽都可以重载
9)信号和槽都可以有默认参数
10)槽函数可以像普通函数一样被调用
11)在槽函数中,调用sender可以获得信号调用者
总结下:
一个类:QObject信号和槽都是这个类的子类
三个宏:Q_OBJECT SIGNAL SLOT
三个保留字:signals, slots, emit
在 Qt 5 中,
QObject::connect()有五个重载:
//第一个,sender 类型是const QObject *,signal 的类型是const char *,receiver 类型是const QObject *,slot 类型是const char *。这个函数将 signal 和 slot 作为字符串处理 QMetaObject::Connection connect(const QObject *, const char *, const QObject *, const char *, Qt::ConnectionType); //第二个,sender 和 receiver 同样是const QObject *,但是 signal 和 slot 都是const QMetaMethod & QMetaObject::Connection connect(const QObject *, const QMetaMethod &, const QObject *, const QMetaMethod &, Qt::ConnectionType); //第三个,sender 同样是const QObject *,signal 和 slot 同样是const char *,但是却缺少了 receiver。这个函数其实是将 this 指针作为 receiver QMetaObject::Connection connect(const QObject *, const char *, const char *, Qt::ConnectionType) const; //第四个,sender 和 receiver 也都存在,都是const QObject *,但是 signal 和 slot 类型则是PointerToMemberFunction。看这个名字就应该知道,这是指向成员函数的指针 QMetaObject::Connection connect(const QObject *, PointerToMemberFunction, const QObject *, PointerToMemberFunction, Qt::ConnectionType) //第五个,前面两个参数没有什么不同,最后一个参数是Functor类型。这个类型可以接受 static 函数、全局函数以及 Lambda 表达式 QMetaObject::Connection connect(const QObject *, PointerToMemberFunction, Functor);
注意:用lambda表达式在.pro中加入 CONFIG += C++11
QT4我们使用了SIGNAL和SLOT这两个宏,将两个函数名转换成了字符串。注意,即使quit()是QApplication的 static 函数,也必须传入一个对象指针。这也是 Qt 4 的信号槽语法的局限之处。另外,注意到connect()函数的 signal 和 slot 都是接受字符串,因此,不能将全局函数或者 Lambda 表达式传入connect()。一旦出现连接不成功的情况,Qt 4 是没有编译错误的(因为一切都是字符串,编译期是不检查字符串是否匹配),而是在运行时给出错误。这无疑会增加程序的不稳定性。
eg:
#include <QApplication> #include <QWidget> #include <QHBoxLayout> #include <QSlider> #include <QSpinBox> int main(int argc,char **argv) { QApplication app(argc,argv); QWidget w; w.setWindowTitle("Enter your age"); QSpinBox *spinbox = new QSpinBox(&w); QSlider *slider = new QSlider(Qt::Horizontal,&w); spinbox->setRange(0,130); slider->setRange(0,130); /* //QT4的写法,使用SIGNAL和SLOT, QObject::connect(slider,SIGNAL(valueChanged(int)),spinbox,SLOT(setValue(int))); QObject::connect(spinbox,SIGNAL(valueChanged(int)),slider,SLOT(setValue(int))); */ //QT5的写法,用指向成员函数的指针 QObject::connect(slider,&QSlider::valueChanged,spinbox,&QSpinBox::setValue); //如果不加下面一行会报错,原因是QSpinBox的确有两个信号:void valueChanged(int)和void valueChanged(const QString &) //使用 Qt 4 的SIGNAL和SLOT宏,因为这两个宏已经指定了参数信息,所以不存在这个问题,解决方法使用函数指针显式指定使用哪一个信号 void(QSpinBox:: *spinBoxSignal)(int) = &QSpinBox::valueChanged; QObject::connect(spinbox,spinBoxSignal,slider,&QSlider::setValue); spinbox->setValue(44); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(spinbox); layout->addWidget(slider); w.setLayout(layout); w.show(); return app.exec(); }
相关文章推荐
- xargs 和 exec
- echarts学习总结(一):jsp整体框架
- Java中管理资源的引用队列相关原理解析
- rk3288_4.4SDK光感patch—CM3218
- Eclipse远程调试
- 多线程代码编写
- CocoaPods更新遇redefinition问题及其它问题汇总
- Html5新元素<canvas>标签画图注意事项
- logging模块使用示例
- listview+edittext完美解决方案
- windows获取pid进程路径
- ORACLE性能调优之执行计划的使用
- scrollview嵌套listview 数据显示不全 问题处理方式集合
- Oracle ODI 11g 安装与技术开发文档
- iOS: TableView如何刷新指定的cell 或section
- Setting and getting the default socket timeout
- 【设计模式】观察者模式
- 支付宝支付
- MVC 使用FileResult导出excel文件实例
- XML:体验学习的乐趣之XML总结