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();
}

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();
}

猜你喜欢

转载自blog.csdn.net/soinlove36/article/details/131152401