Qt 学习(四) —— 信号和槽

1. 信号和槽的机制

当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,将想要处理的信号和自己的一个函数(槽函数(slot))绑定并处理这个信号。

1.1. 信号和槽的属性

信号和槽都是函数
但信号是类的成员函数。
而槽不仅可以是类的成员函数,还可以是静态函数、全局函数和 Lambda 表达式。

项目信号
声明
实现
参数可有可无可有可无
返回值
1.2. 信号和槽的声明

信号函数必须使用 signals 关键字来声明,而且 signals 前不能用 public、private、protected 等限定,因为信号函数默认是 public 的。
但槽函数是类的成员函数时可以被 public、private、protected 限定,而且槽函数需用 slots 关键字来声明(虽然新版本的 Qt 已经不使用 slots,但为了兼容性仍建议使用),类似这样:

//信号的声明
signals:
	void sig1();
//槽的声明
public slots:
	void slot1();
1.3. 信号和槽的参数

他们的参数都是可有可无,但如果有参数,对于可以相连接的信号函数和槽函数,信号函数的参数个数不能少于槽函数,而且对应的参数的数据类型必须一致。

信号函数槽函数正误描述
signal(int, float, double)slot(int, float, double)正确参数个数一致,类型一一对应
signal(int, float, double)slot(int, float)正确参数个数,信号多于槽,类型一一对应
signal(int, float, double)slot()正确参数个数,信号多于槽,类型一一对应
signal(int, float, double)slot(double, int, float)错误参数类型不对应
signal(int, float)slot(int, float, double)错误参数个数信号少于槽

助记:槽要什么信号就得给什么,能多不能少。

2. 信号和槽的连接与断开
2.1. 连接

使用 connect() 函数对信号和槽进行连接,对于这个函数,Qt4 和 Qt5 有所不同。
Qt4:

connect(sender,  // 信号发送者
		SIGNAL(sig1(int, QString)),  // 信号函数
		receiver,  // 信号接收者
		SLOT(slot1(int, QString))); // 槽函数

Qt5:

connect(sender,  // 信号发送者
		&sig1,  // 信号函数地址
		receiver,  // 信号接收者
		&slot1); // 槽函数地址

虽然 Qt4 版本有指明函数参数的数据类型,但没有编译期错误检查,比如上面1.3表格中的例子:

信号函数槽函数正误描述
signal(int, float, double)slot(double, int, float)错误参数类型不对应

Qt4版本的连接函数,编译器是不报错的,但在执行时会出现错误:

connect(sender,  // 信号发送者
		SIGNAL(signal(int, float, double) ),  // 信号函数
		receiver,  // 信号接收者
		SLOT(slot(double, int, float))); // 槽函数

而在 Qt5 中,会进行编译期错误检查,所以上述代码编译时会报错,更加安全。

2.2. 断开

使用 disconnect() 函数使信号和槽的连接断开。
基本用法是断开一个信号和一个槽的连接:

disconnect(sender,  // 信号发送者
		&sig1,  // 信号函数地址
		receiver,  // 信号接收者
		&slot1); // 槽函数地址

另外,还有以下用法:
断开一个对象(信号发送者)的所有信号的所有连接:

disconnect(sender, 0, 0, 0); 
//等价于
sender->disconnect();

断开一个信号的所有连接:

disconnect(sender, &sig1, 0, 0); 
//等价于
sender->disconnect(&sig1);

断开一个对象(信号发送者)与另一个对象(信号接收者)的所有连接:

disconnect(sender, 0, receiver, 0); 
//等价于
sender->disconnect(receiver);
3. 其他 Tips
3.1. 信号连接信号

信号连接信号不仅可以和槽连接,也可以和信号连接。

connect(sender,  // 信号发送者
		&sig1,  // 信号函数地址
		receiver,  // 信号接收者
		&sig2); // 另一个信号函数地址
3.2. 信号与槽(信号)的个数对应

3.2.1. 一个信号连接多个槽(信号)
一个信号可以连接多个槽(信号)函数,并且被连接的槽(信号)函数的触发顺序是随机的,不能控制。

connect(sender, &sig1, receiver, &sig2); 
connect(sender, &sig1, receiver, &sig3);
connect(sender, &sig1, receiver1, &slot1);
connect(sender, &sig1, receiver2, &slot2);

3.2.2. 多个信号连接一个槽(信号)
一个槽函数可以同时被多个信号连接。

connect(sender1, &sig1, receiver, &slot); 
connect(sender2, &sig2, receiver, &slot);
connect(sender3, &sig3, receiver, &slot);
connect(sender4, &sig4, receiver, &slot);

总结:信号与槽的对应,一对一,一对多,多对一。

3.3. 信号的触发
  1. 通过用户操作触发,比如点击、停留。
  2. 与另一个信号连接,通过另一个信号触发。
  3. 使用 emit 关键字触发,比如:
void signal()
{
	emit sig();
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万俟淋曦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值