QT 的信号与槽机制介绍(二)

tsignal.h

 1 ...
2
3 class TsignalApp:public QMainWindow
4
5 {
6
7 Q_OBJECT
8
9 // 信号声明区
10
11 signals:
12
13 // 声明信号 mySignal()
14
15 void mySignal();
16
17 // 声明信号 mySignal(int)
18
19 void mySignal(int x);
20
21 // 声明信号 mySignalParam(int,int)
22
23 void mySignalParam(int x,int y);
24
25 // 槽声明区
26
27 public slots:
28
29 // 声明槽函数 mySlot()
30
31 void mySlot();
32
33 // 声明槽函数 mySlot(int)
34
35 void mySlot(int x);
36
37 // 声明槽函数 mySignalParam (int,int)
38
39 void mySignalParam(int x,int y);
40
41 }

//tsignal.cpp

 1 TsignalApp::TsignalApp()
2
3 {
4
5 // 将信号 mySignal() 与槽 mySlot() 相关联
6
7 connect(this,SIGNAL(mySignal()),SLOT(mySlot()));
8
9 // 将信号 mySignal(int) 与槽 mySlot(int) 相关联
10
11 connect(this,SIGNAL(mySignal(int)),SLOT(mySlot(int)));
12
13 // 将信号 mySignalParam(int,int) 与槽 mySlotParam(int,int) 相关联
14
15 connect(this,SIGNAL(mySignalParam(int,int)),SLOT(mySlotParam(int,int)));
16
17 }
18
19 // 定义槽函数 mySlot()
20
21 void TsignalApp::mySlot()
22
23 {
24
25 QMessageBox::about(this,"Tsignal", "This is a signal/slot sample without
26
27 parameter.");
28
29 }
30
31 // 定义槽函数 mySlot(int)
32
33 void TsignalApp::mySlot(int x)
34
35 {
36
37 QMessageBox::about(this,"Tsignal", "This is a signal/slot sample with one
38
39 parameter.");
40
41 }
42
43 // 定义槽函数 mySlotParam(int,int)
44
45 void TsignalApp::mySlotParam(int x,int y)
46
47 {
48
49 char s[256];
50
51 sprintf(s,"x:%d y:%d",x,y);
52
53 QMessageBox::about(this,"Tsignal", s);
54
55 }
56
57 void TsignalApp::slotFileNew()
58
59 {
60
61 // 发射信号 mySignal()
62
63 emit mySignal();
64
65 // 发射信号 mySignal(int)
66
67 emit mySignal(5);
68
69 // 发射信号 mySignalParam(5,100)
70
71 emit mySignalParam(5,100);
72
73 }

 

应注意的问题

信号与槽机制是比较灵活的,但有些局限性我们必须了解,这样在实际的使用过程中做到有的放矢,避免产生一些错误。下面就介绍一下这方面的情况。

1 .信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活性,因此在速度上还是有所损失,当然这种损失相对来说是比较小的,通过在一台 i586-133 的机器上测试是 10 微秒(运行 Linux),可见这种机制所提供的简洁性、灵活性还是值得的。但如果我们要追求高效率的话,比如在实时系统中就要尽可能的少用这种机制。

2 .信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也有可能产生死循环。因此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。例如 , 在前面给出的例子中如果在 mySlot() 槽函数中加上语句 emit mySignal() 即可形成死循环。

3 .如果一个信号与多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是随机的。

4. 宏定义不能用在 signal 和 slot 的参数中。

既然 moc 工具不扩展 #define,因此,在 signals 和 slots 中携带参数的宏就不能正确地工作,如果不带参数是可以的。例如,下面的例子中将带有参数的宏 SIGNEDNESS(a) 作为信号的参数是不合语法的:

 1 #ifdef ultrix
2
3 #define SIGNEDNESS(a) unsigned a
4
5 #else
6
7 #define SIGNEDNESS(a) a
8
9 #endif
10
11 class Whatever : public QObject
12
13 {
14
15 [...]
16
17 signals:
18
19 void someSignal( SIGNEDNESS(a) );
20
21 [...]
22
23 };

 

5. 构造函数不能用在 signals 或者 slots 声明区域内。

的确,将一个构造函数放在 signals 或者 slots 区内有点不可理解,无论如何,不能将它们放在 private slots、protected slots 或者 public slots 区内。下面的用法是不合语法要求的:

 1 class SomeClass : public QObject
2
3 {
4
5 Q_OBJECT
6
7 public slots:
8
9 SomeClass( QObject *parent, const char *name )
10
11 : QObject( parent, name ) {} // 在槽声明区内声明构造函数不合语法
12
13 [...]
14
15 };

6. 函数指针不能作为信号或槽的参数。

例如,下面的例子中将 void (*applyFunction)(QList*, void*) 作为参数是不合语法的:

 1 class someClass : public QObject
2
3 {
4
5 Q_OBJECT
6
7 [...]
8
9 public slots:
10
11 void apply(void (*applyFunction)(QList*, void*), char*); // 不合语法
12
13 };

你可以采用下面的方法绕过这个限制:

 1 typedef void (*ApplyFunctionType)(QList*, void*);
2
3 class someClass : public QObject
4
5 {
6
7 Q_OBJECT
8
9 [...]
10
11 public slots:
12
13 void apply( ApplyFunctionType, char *);
14
15 };

 

7. 信号与槽不能有缺省参数。

既然 signal->slot 绑定是发生在运行时刻,那么,从概念上讲使用缺省参数是困难的。下面的用法是不合理的:

 1 class SomeClass : public QObject
2
3 {
4
5 Q_OBJECT
6
7 public slots:
8
9 void someSlot(int x=100); // 将 x 的缺省值定义成 100,在槽函数声明中使用是错误的
10
11 };

 

8. 信号与槽也不能携带模板类参数。

如果将信号、槽声明为模板类参数的话,即使 moc 工具不报告错误,也不可能得到预期的结果。 例如,下面的例子中当信号发射时,槽函数不会被正确调用:

 1 [...]
2
3 public slots:
4
5 void MyWidget::setLocation (pair<int,int> location);
6
7 [...]
8
9 public signals:
10
11 void MyObject::moved (pair<int,int> location);

 

但是,你可以使用 typedef 语句来绕过这个限制。如下所示:

 1 typedef pair<int,int> IntPair;
2
3 [...]
4
5 public slots:
6
7 void MyWidget::setLocation (IntPair location);
8
9 [...]
10
11 public signals:
12
13 void MyObject::moved (IntPair location);

 

这样使用的话,你就可以得到正确的结果。

9. 嵌套的类不能位于信号或槽区域内,也不能有信号或者槽。

例如,下面的例子中,在 class B 中声明槽 b() 是不合语法的,在信号区内声明槽 b() 也是不合语法的。

 1 class A
2
3 {
4
5 Q_OBJECT
6
7 public:
8
9 class B
10
11 {
12
13 public slots: // 在嵌套类中声明槽不合语法
14
15 void b();
16
17 [....]
18
19 };
20
21 signals:
22
23 class B
24
25 {
26
27 // 在信号区内声明嵌套类不合语法
28
29 void b();
30
31 [....]
32
33 }:
34
35 };

 

10. 友元声明不能位于信号或者槽声明区内。

相反,它们应该在普通 C++ 的 private、protected 或者 public 区内进行声明。下面的例子是不合语法规范的:

 1 class someClass : public QObject
2
3 {
4
5 Q_OBJECT
6
7 [...]
8
9 signals: // 信号定义区
10
11 friend class ClassTemplate; // 此处定义不合语法
12
13 };

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值