Qt那点事儿(二)

转载自:http://www.cnblogs.com/andreitang/archive/2011/08/08/2128505.html  谢谢无私的分享

第二回 拒签,不只天朝有

上回说到,柯南君展示了Qt无耻的一面后,众道友心灰意冷。修仙的修仙,搞基的搞基。原本热闹的Qt道场,一下子冷清了下来。只剩哥一个人坐在联想大厦的塑像前作冥想状,“世界如果失去了Qt会怎样“?会变成知书识仪,天下大同的理想世界吗?中国五千年的24部血泪史昭示了”This is just a dream“。一个无耻倒下了,一个更无耻的又站起来。这时大屏幕上的图片映入贫道的眼帘,

霎那间贫道的内心被震撼了,终于领悟了修仙的真谛,那就是“誓将揭露Qt无耻的事业进行到底”。此时的哥又斗志昂扬,走在了修仙的大道上。

各位道友请看此例,

?
void  NotifyOtherThread( DWORD  dwOtherThreadID)
{
     CString str = "i am here" ;
     ::PostThreadMessage(dwOtherThreadID,
         WS_NOTIFY,
         &str,
         NULL);
 
}

   我们知道在Windows的世界里,用Post跨线程发送消息是异步的,如果按照上面的实例,把local 类(结构)变量作为参数发送,那么接受方得到的参数内容会是混乱的,从而引起程序的崩溃。因为他一出函数体就被释放掉了。所以,我们从小就被告知,local类变量不能作为Post的参数。

 那么在Qt中还是这样吗?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
class  MyTestA : public  QObject
{
     Q_OBJECT
public :
     void  emitSignal()
     {
        signalMyTestA( "I am here." );
     }
 
public  slots:
     void  slotMyTestA()
     {
         qDebug()<< "slotMyTestA is called." ;
     }
signals:
     void  signalMyTestA(QString str);
};
 
class  MyTestB : public  QObject
{
     Q_OBJECT
public  slots:
     void  slotMyTestB(QString str)
     {
         qDebug()<< "string is " <<str;
     }
signals:
     void  signalMyTestB();
};
 
extern  MyTestB *g_pMyTestB;
extern  MyTestA *g_pMyTestA;
class  MyTestC : public  QThread
{
     Q_OBJECT
public :
 
     MyTestC():QThread(NULL)
     {
     }
 
     void  run()
     {
         MyTestA a;
         QObject::connect(&a,SIGNAL(signalMyTestA(QString)),g_pMyTestB,SLOT(slotMyTestB(QString)));
         a.emitSignal();
         exec();
     }
 
public  slots:
     void  slotMyTestC()
     {
         qDebug()<< "slotMyTestC is called." ;
     }
signals:
     void  signalMyTestC();
 
 
};
 
///
 
MyTestB *g_pMyTestB = NULL;
MyTestA *g_pMyTestA = NULL;
int  main( int  argc, char  *argv[])
{
     QApplication app(argc, argv);
 
 
     MyTestB b;
     g_pMyTestB = &b;
 
     MyTestC c;
     c.start();
 
 
 
     return  app.exec();
}

只见输出窗口打出了:string is  "I am here." 居然没有发生对象混乱,程序安然无恙,Local QString参数完美地被发送到了另外的线程。众道友的失落的心又重新热了起来,内心对Qt又充满了无限的期望。但俗话说得好,一朝被蛇咬,十年怕井绳。一些细心的道友,又把QString换成了QByteArray,QDate,QPixmap等常用的Qt类,无一错乱。十分,十分,只见铺天盖地的写有十的积分牌举了起来。此时语言已经是多余的了。终于不用再为Local变量烦恼了,跨线程不能使用Local变量这一无耻的行规终于被扫入了历史的垃圾箱。从此Coder道友们站起来了........。在一片赞扬声中,贫道则陷入了深深的思索中,事有反常即为妖。

突然思绪一闪,柯南君的音容相貌又浮现在了眼前。此时贫道把代码稍微改写了下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
struct  sOwn
{
    QString m_str;
};
 
class  MyTestA : public  QObject
{
     Q_OBJECT
public :
     void  emitSignal()
     {
         sOwn s;
         s.m_str = "i am here" ;
         signalMyTestA(s);
     }
 
public  slots:
     void  slotMyTestA()
     {
         qDebug()<< "slotMyTestA is called." ;
     }
signals:
     void  signalMyTestA(sOwn sItem);
};
 
class  MyTestB : public  QObject
{
     Q_OBJECT
public  slots:
     void  slotMyTestB(sOwn sItem)
     {
         qDebug()<< "string is " <<sItem.m_str;
     }
signals:
     void  signalMyTestB();
};
 
extern  MyTestB *g_pMyTestB;
extern  MyTestA *g_pMyTestA;
class  MyTestC : public  QThread
{
     Q_OBJECT
public :
 
     MyTestC():QThread(NULL)
     {
     }
 
     void  run()
     {
         MyTestA a;
         QObject::connect(&a,SIGNAL(signalMyTestA(sOwn)),g_pMyTestB,SLOT(slotMyTestB(sOwn)));
         a.emitSignal();
         exec();
     }
 
public  slots:
     void  slotMyTestC()
     {
         qDebug()<< "slotMyTestC is called." ;
     }
signals:
     void  signalMyTestC();
 
 
};
 
/
 
MyTestB *g_pMyTestB = NULL;
MyTestA *g_pMyTestA = NULL;
int  main( int  argc, char  *argv[])
{
     QApplication app(argc, argv);
 
 
     MyTestB b;
     g_pMyTestB = &b;
 
     MyTestC c;
     c.start();
 
 
 
     return  app.exec();
}

一道闪电从空中划过,当代码执行到"QObject::connect(&a,SIGNAL(signalMyTestA(sOwn)),g_pMyTestB,SLOT(slotMyTestB(sOwn)));"这一句时,”QObject::connect: Cannot queue arguments of type 'sOwn' “刺眼地跳了出来。这句话通俗地说就是,你被发好人卡了,你被拒签了..., 总之就是因为你的对象不是Q家人,你就进不了Q家门,自然就connect不了slot。

这一刻Qt你又赢了,你又一次玩弄了众道友的感情,你继承了中国足球的光荣的传统。各届国家队在这一刻灵魂附体!在这一刻你不是一个人在战斗!你就像中国足球那样,在人绝望的时候给人希望,在希望的时候给人以绝望。

此时众道友仰天长叹,大声质问道,Qt你来自希望国,秉承着“All object is created equal”的信念(Qt内牛满面,哥本挪威人,奈何成花旗),却行歧视之勾当,意欲何为?更有欲到花旗传道的道友,挥舞着印有No Pass的护照,叹道,“人被拒签,难道自己写的程序也要被拒签,朗朗乾坤,公理何在,天理何存”。说完就要自碎金丹,化作散仙,不再为这个充满着无耻之徒的尘世所困扰。就在这时,一道红光飞过,仔细一看是一条鲜红的红领巾,上面写着几个屎黄色的希望文:

"qRegisterMetaType"

落款人:红领巾。

贫道急忙把此函数放到代码中,

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
struct  sOwn
{
    QString m_str;
};
 
class  MyTestA : public  QObject
{
     Q_OBJECT
public :
     void  emitSignal()
     {
         sOwn s;
         s.m_str = "i am here" ;
         signalMyTestA(s);
     }
 
public  slots:
     void  slotMyTestA()
     {
         qDebug()<< "slotMyTestA is called." ;
     }
signals:
     void  signalMyTestA(sOwn sItem);
};
 
class  MyTestB : public  QObject
{
     Q_OBJECT
public  slots:
     void  slotMyTestB(sOwn sItem)
     {
         qDebug()<< "string is " <<sItem.m_str;
     }
signals:
     void  signalMyTestB();
};
 
extern  MyTestB *g_pMyTestB;
extern  MyTestA *g_pMyTestA;
class  MyTestC : public  QThread
{
     Q_OBJECT
public :
 
     MyTestC():QThread(NULL)
     {
     }
 
     void  run()
     {
         MyTestA a;
         qRegisterMetaType<sOwn>( "sOwn" );
         QObject::connect(&a,SIGNAL(signalMyTestA(sOwn)),g_pMyTestB,SLOT(slotMyTestB(sOwn)));
         a.emitSignal();
         exec();
     }
 
public  slots:
     void  slotMyTestC()
     {
         qDebug()<< "slotMyTestC is called." ;
     }
signals:
     void  signalMyTestC();
 
 
};
/
 
MyTestB *g_pMyTestB = NULL;
MyTestA *g_pMyTestA = NULL;
int  main( int  argc, char  *argv[])
{
     QApplication app(argc, argv);
 
 
     MyTestB b;
     g_pMyTestB = &b;
 
     MyTestC c;
     c.start();
 
 
 
     return  app.exec();
}

string is  "I am here." 重回大地,众人又开始捻胡微笑,皆叹Qt的人性化。不用收入证明,不用公司邀请信,不用签证面试,只要你用了qRegisterMetaType,你就是Q家人了。

所以,当signal异步调用slot时,如果你的对象不是Qt所支持的,就需要调用qRegisterMetaType,而后就可以将Local class变量放到signal中,安全地传递给slot。

一切就是这么简单。Ye!!!,众道友做了个00后的标准动作,以表达自己的欢乐之情。

但是快乐的时光总是短暂的,又一幕悲剧拉开了序幕。

话说C++三朝元老,int。最近痴迷欧美音乐,给自己取了个鼎鼎响亮的艺名"雷帝嘎嘎"(LADYGAGA)。结果,

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
typedef  int  LADYGAGA;
 
struct  sOwn
{
    QString m_str;
};
 
class  MyTestA : public  QObject
{
     Q_OBJECT
public :
     void  emitSignal()
     {
         int  i = 9;
         signalMyTestA(i);
     }
 
public  slots:
     void  slotMyTestA()
     {
         qDebug()<< "slotMyTestA is called." ;
     }
signals:
     void  signalMyTestA(LADYGAGA lg);
};
 
class  MyTestB : public  QObject
{
     Q_OBJECT
public  slots:
     void  slotMyTestB(LADYGAGA lg)
     {
         qDebug()<< "string is " <<lg;
     }
signals:
     void  signalMyTestB();
};
 
extern  MyTestB *g_pMyTestB;
extern  MyTestA *g_pMyTestA;
class  MyTestC : public  QThread
{
     Q_OBJECT
public :
 
     MyTestC():QThread(NULL)
     {
     }
 
     void  run()
     {
         MyTestA a;
         QObject::connect(&a,SIGNAL(signalMyTestA(LADYGAGA)),g_pMyTestB,SLOT(slotMyTestB(LADYGAGA)));
         a.emitSignal();
         exec();
     }
 
public  slots:
     void  slotMyTestC()
     {
         qDebug()<< "slotMyTestC is called." ;
     }
signals:
     void  signalMyTestC();
 
 
};
//
MyTestB *g_pMyTestB = NULL;
MyTestA *g_pMyTestA = NULL;
int  main( int  argc, char  *argv[])
{
     QApplication app(argc, argv);
 
 
     MyTestB b;
     g_pMyTestB = &b;
 
     MyTestC c;
     c.start();
 
 
 
     return  app.exec();
}

本年度最具爆炸性新闻诞生了“QObject::connect: Cannot queue arguments of type 'LADYGAGA',(Make sure 'LADYGAGA' is registered using qRegisterMetaType().)”世界震惊了,大家宁可相信“发改委宣布降低油价”,也不愿相信,编程界基本数据类型的三朝元老,久经考验的C++主义战士,int同志居然因为使用众人皆知的艺名connect slot,被拒签了。三大社(美联社,法新社,路透社)联合发文<<悲剧,三朝元老使用艺名,被拒签>>。2月30号X民日报头版发表评论员文章《老同志,倚老卖老要不得》。

从上诉评论中我们不难看出"当signal和slots是异步时,哪怕数据类型用qRegisterMetaTyoe注册过,甚至是基本数据类型,connect用的参数类型不是注册名,而是typedef或者define的别名,connect也会失败,如果要使用别名,也需要对别名进行重新注册。Qt只认名,不认人"。对于上面的例子,如果要使connect能正常使用,需调用qRegisterMetaType<LADYGAGA>("LADYGAGA");,虽然LADYGAGA其实就是int。

Qt总是在意想不到的时间,意想不到的地点,展示其无耻的一面。

太史公曾曰,世上无耻者,皆不过Qt也。

古人不曾欺我。

而众道友此时却没有因为Qt的再次无耻,而愤愤不平,反而露出一丝猥琐的笑容,心里不禁乐道,老东西,你也有今天。

而贫道又陷入了沉思,Qt你的底线到底在哪里?


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值