📄 qt信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.htm
字号:
: "qt_invoke", membcode );<BR>/* 创建一个新的信号/反应槽连接
*/<BR>clist->append( c ); /* 信号源端加入这一对连接
*/<BR>if ( !r->senderObjects ) {<BR>/*
类似于信号源端,反应槽端的连接列表也是动态创建的 */<BR>r->senderObjects
= new
QObjectList;<BR>}<BR>r->senderObjects->append(
s ); /* 反应槽端加入这一对连接
*/<BR>}<BR>到此,信号与反应槽的连接已建立完毕,那么信号产生时又是如何触发反应槽的呢?从QObject的定义中可以看出其有多个activate_signal的成员函数,这些函数都是protected的,也即只有其自身或子类才可以使用。看一下它的实现:<BR>void
QObject::activate_signal( QConnectionList *clist,
QUObject *o )<BR>{<BR>if ( !clist ) /* 有效性检查
*/<BR>return;<BR>QObject *object;<BR>QConnection
*c;<BR>if ( clist->count() == 1 ) {<BR>/*
对某一个对象的一个具体信号来说,一般只有一种反应槽与之相连,这样事先判断一下可以加快处理速度
*/<BR>c = clist->first();<BR>object =
c->object();<BR>sigSender = this;<BR>if (
c->memberType() == QSIGNAL_CODE
)<BR>object->qt_emit( c->member(), o ); /*
信号级连 */<BR>else<BR>object->qt_invoke(
c->member(), o );/* 调用反应槽函数 */<BR>} else
{<BR>QConnectionListIt it(*clist);<BR>while (
(c=it.current()) ) { /* 有多个连接时,逐一扫描
*/<BR>++it;<BR>object =
c->object();<BR>sigSender = this;<BR>if (
c->memberType() == QSIGNAL_CODE
)<BR>object->qt_emit( c->member(), o ); /*
信号级连 */<BR>else<BR>object->qt_invoke(
c->member(), o ); /* 调用反应槽函数
*/<BR>}<BR>}<BR>}<BR>至此我们已经可以基本了解Qt中信号/反应槽的流程。我们再看一下Qt为此而新增的语法:三个关键字:slots、signals和emit,三个宏:SLOT()、SIGNAL()和Q_OBJECT。在头文件qobjectdefs.h中,我们可以看到这些新增语法的定义如下:<BR>#define
slots // slots: in class<BR>#define signals
protected // signals: in class<BR>#define emit //
emit signal<BR>#define SLOT(a) "1"#a<BR>#define
SIGNAL(a)
"2"#a<BR>由此可知其实三个关键字没有做什么事情,而SLOT()和SIGNAL()宏也只是在字符串前面简单地加上单个字符,以便<BR>程序仅从名称就可以分辨谁是信号、谁是反应槽。中间编译程序moc.exe则可以根据这些关键字和宏对相应的函数进行“翻译”,以便在C++编译器中编译。剩下一个宏Q_OBJECT比较复杂,它的定义如下:<BR>#define
Q_OBJECT \<BR>publi \<BR>virtual QMetaObject
*metaObject() const { \<BR>return
staticMetaObject(); \<BR>}<BR>\<BR>virtual const
char *className() const; \<BR>virtual void*
qt_cast( const char* ); \<BR>virtual bool
qt_invoke( int, QUObject* ); \<BR>virtual bool
qt_emit( int, QUObject* );
\<BR>QT_PROP_FUNCTIONS<BR>\<BR>static QMetaObject*
staticMetaObject(); \<BR>QObject* qObject() {
return (QObject*)this; }
\<BR>QT_TR_FUNCTIONS<BR>\<BR>private: \<BR>static
QMetaObject
*metaObj;<BR>从定义中可以看出该宏的作用有两个:一是对与自己相关的QMetaObject中间类操作进行声明,另一个是对信号的释放操作和反应槽的激活操作进行声明。当moc.exe对头文件进行预编译之后,将会产生一个可供C++编译器编译的源文件。以上述的Demo类为例,假设它的代码文件分别为d
e m o . h和d e m o . c p p
,预编译后将产生<BR>moc_demo.cpp,其主要内容如下:<BR>QMetaObject
*Demo::metaObj = 0;<BR>void
Demo::initMetaObject()<BR>{<BR>if ( metaObj
)<BR>return;<BR>if ( strcmp(QObject::className(),
"QObject") != 0
)<BR>badSuperclassWarning("Demo","QObject");<BR>(void)
staticMetaObject();<BR>}<BR>QMetaObject*
Demo::staticMetaObject()<BR>{<BR>if ( metaObj
)<BR>return metaObj;<BR>(void)
QObject::staticMetaObject();<BR>typedef
void(Demo::*m1_t0)(int);<BR>m1_t0 v1_0 =
Q_AMPERSAND Demo::setValue; /* 定位反应槽的入口
*/<BR>QMetaData *slot_tbl =
QMetaObject::new_metadata(1);<BR>/* 新建一个反应槽数据
*/<BR>QMetaData::Access *slot_tbl_access =
QMetaObject::new_metaaccess(1);<BR>slot_tbl[0].name
= "setValue(int)"; /* 反应槽名称 */<BR>slot_tbl[0].ptr
= *((QMember*)&v1_0);<BR>/*
通过反应槽名称可以找到反应槽的入口指针 */<BR>slot_tbl_access[0] =
QMetaData::Public; /* 权限类型 */<BR>typedef
void(Demo::*m2_t0)(int);<BR>m2_t0 v2_0 =
Q_AMPERSAND Demo::valueChanged; /* 定位信号的入口
*/<BR>QMetaData *signal_tbl =
QMetaObject::new_metadata(1); /* 新建信号数据
*/<BR>signal_tbl[0].name = "valueChanged(int)"; /*
信号名称 */<BR>signal_tbl[0].ptr =
*((QMember*)&v2_0);<BR>/* 通过信号名称可以找到信号的入口指针
*/<BR>metaObj = QMetaObject::new_metaobject(<BR>/*
创建一个与demo类相关的QMetaObject对象 */<BR>"Demo",
"QObject",<BR>slot_tbl, 1,<BR>signal_tbl, 1,<BR>0,
0 );<BR>metaObj->set_slot_access(
slot_tbl_access ); /* 设置权限 */<BR>return
metaObj;<BR>}<BR>// 有信号时即激活对应的反应槽或另一个信号<BR>void
Demo::valueChanged( int t0
)<BR>{<BR>activate_signal( "valueChanged(int)", t0
);<BR>}<BR>该文件中既没有Qt特有的关键字,也没有特殊的宏定义,完全符合普通的C++语法,因此可以顺利编译和链接。<BR><BR></DIV></DIV></TD></TR></TBODY></TABLE>
<P style="MARGIN: 5px; LINE-HEIGHT: 150%"></P></TD></TR>
<TR>
<TD height=25> <FONT
color=#000099><B>原文地址</B></FONT> <A
href="http://www.qobject.com/simple/index.php?t1827.html"
target=_blank>http://www.qobject.com/simple/index.php?t1827.html</A>
</TD></TR>
<TR>
<TD align=middle height=25><FONT color=#295200>发表于:
2007-08-14,修改于: 2007-08-14 16:19,已浏览178次,有评论0条</FONT> <A
id=star title=推荐这篇文章
onclick="NewWindows(this.href);return false;"
href="http://blog.chinaunix.net/u2/star.php?blogid=30686&artid=359959">推荐</A>
<A id=complaint title=投诉这篇文章
onclick="NewWindows(this.href);return false;"
href="http://blog.chinaunix.net/u2/complaint.php?blogid=30686&artid=359959">投诉</A>
</TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD width=7 height=7><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/w_left_buttom.gif"
border=0></TD>
<TD bgColor=#f3f3f3></TD>
<TD width=7 height=7><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/w_right_buttom.gif"
border=0></TD></TR></TBODY></TABLE>
<TR>
<TD width=11 height=11><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/g_left_bottom.gif"
border=0></TD>
<TD bgColor=#dddddd></TD>
<TD width=11 height=11><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/g_right_bottom.gif"
border=0></TD></TR></TBODY></TABLE><BR><BR>
<TABLE style="BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0
width="100%" border=0>
<TBODY>
<TR>
<TD width=11 height=11><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/g_left_top.gif"
border=0></TD>
<TD width="99%" bgColor=#dddddd height=11></TD>
<TD width=11 height=11><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/g_right_top.gif"
border=0></TD></TR>
<TR>
<TD vAlign=top align=middle width="100%" bgColor=#dddddd
colSpan=3><B>网友评论</B> <BR>
<TABLE style="BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0
width="96%" border=0>
<TBODY>
<TR>
<TD width=7 height=7><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/w_left_top.gif"
border=0></TD>
<TD width="100%" bgColor=#f3f3f3></TD>
<TD width=7 height=7><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/w_right_top.gif"
border=0></TD></TR>
<TR>
<TD align=middle bgColor=#f3f3f3 colSpan=3>
<TABLE style="BORDER-COLLAPSE: collapse" cellSpacing=0
cellPadding=0 width=700 align=center border=0>
<TBODY>
<TR>
<TD style="COLOR: #0000cc" height=25> 发表评论 </TD></TR>
<TR>
<TD height=25><IFRAME name=comment
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/comment.htm"
frameBorder=0 width=640
height=160></IFRAME></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD width=7 height=7><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/w_left_buttom.gif"
border=0></TD>
<TD bgColor=#f3f3f3></TD>
<TD width=7 height=7><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/w_right_buttom.gif"
border=0></TD></TR></TBODY></TABLE>
<TR>
<TD width=11 height=11><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/g_left_bottom.gif"
border=0></TD>
<TD bgColor=#dddddd></TD>
<TD width=11 height=11><IMG alt=""
src="QT信号机制(全文) - 关注性能 - 飞翔,嵌入式linux.files/g_right_bottom.gif"
border=0></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<CENTER></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -