<pre id=\"best-answer-content\" class=\"reply-text mb10\">一: [ 每个对象 ] 都有一个相应的纪录该对象的 [ 元对象 ]
关于元对象的类:
QMetaObject 类:
/******************* 生成元对象需要的输入参数 *****************/
// 类名
const char * const class_name,
// 父类名
QMetaObject *superclass,
// 记录 slot 信息
const QMetaData * const slot_data,
// 记录槽的个数
int n_slots,
// 记录 signal 信息
const QMetaData * const signal_data,
// 记录信号的个数
int n_signals
/******************* 元对象类提供的方法 **************************/
int numSlots( bool super = FALSE ) const;// 返回槽的个数
int numSignals( bool super = FALSE ) const;// 返回信号的个数
int findSlot( const char *, bool super = FALSE ) const;// 查找槽
int findSignal( const char *, bool super = FALSE ) const;// 查找信号
// 返回指定位置的槽
const QMetaData *slot( int index, bool super = FALSE ) const;
// 返回指定位置的信号
const QMetaData *signal( int index, bool super = FALSE ) const;
// 所有槽名字的列表
QStrListslotNames( bool super = FALSE ) const;
// 所有信号名字的列表
QStrListsignalNames( bool super = FALSE ) const;
// 槽的起始索引
int slotOffset() const;
// 信号的起始索引
int signalOffset() const;
/*********************** 两个获取类的元对象的方法 *****************/
static QMetaObject *metaObject( const char *class_name );
static bool hasMetaObject( const char *class_name );
QMetaData 类:
// 记录元对象数据 for 信号与槽
struct QMetaData
{
const char *name;
// 名称
const QUMethod* method;
// 详细描述信息
enum Access { Private, Protected, Public };
Access access;
// 访问权限
};
二: [QObject 类实现了信号与槽机制 ]
它利用元对象纪录的信息,实现了信号与槽机制
( 1 )信号与槽建立连接的实现
接口函数:
// 连接
// 参数(发送对象,信号,接收对象,处理信号的信号 / 槽)
static boolconnect( const QObject *sender, const char *signal,
const QObject *receiver, const char *member );
bool connect(const QObject *sender, const char *signal,
const char *member ) const;
static booldisconnect( const QObject *sender, const char *signal,
const QObject *receiver, const char *member );
bool disconnect(const char *signal=0,
const QObject *receiver=0, const char *member=0 );
bool disconnect( const QObject *receiver, const char *member=0 );
// 连接的内部实现
// (发送对象,信号的索引,接收对象,处理信号的类型,处理信号信号 / 槽的索引)
static void connectInternal(const QObject *sender, int signal_index,
const QObject *receiver, int membcode, int member_index );
static bool disconnectInternal(const QObject *sender, int signal_index,
const QObject *receiver, int membcode, int member_index );
信号与槽连接的实现原理:
① 阶段
bool QObject::connect( const QObject *sender,// 发送对象
const char *signal,// 信号
const QObject *receiver, // 接收对象
const char *member // 槽
)
{
// 检查发送对象,信号,接收对象,槽不为 null
if ( sender == 0 || receiver == 0 || signal == 0 || member == 0 ) {
return FALSE;
}
// 获取发送对象的元对象
QMetaObject *smeta = sender-metaObject();
// 检查信号
if ( !check_signal_macro( sender, signal, \"connect\", \"bind\" ) )
return FALSE;
// 获取信号的索引
int signal_index = smeta-findSignal( signal, TRUE );
if ( signal_index0 ) {
// normalize and retry
nw_signal = qt_rmWS( signal-1 ); // remove whitespace
signal = nw_signal.data() 1;
// skip member type code
signal_index = smeta-findSignal( signal, TRUE );
}
// 如果信号不存在,则退出
if ( signal_index0) {
// no such signal
return FALSE;
}
// 获取信号的元数据对象
const QMetaData *sm = smeta-signal( signal_index, TRUE );
// 获取信号名字
signal = sm-name;
// 获取处理信号的类型(是信号 / 槽)
int membcode = member[0] - \'0\';
// get member code
// 发送信号对象
QObject *s = (QObject *)sender;
// we need to change them
// 接收信号对象
QObject *r = (QObject *)receiver;
// internally
// 获取接收对象的元对象
QMetaObject *rmeta = r-metaObject();
int member_index = -1;
switch ( membcode ) {
// get receiver member
case QSLOT_CODE:// 如果是槽
// 获取槽索引
member_index = rmeta-findSlot( member, TRUE );
if ( member_index0 ) {
// normalize and retry
nw_member = qt_rmWS(member);
// remove whitespace
member = nw_member;
member_index = rmeta-findSlot( member, TRUE );
}
break;
case QSIGNAL_CODE:// 如果是信号
// 获取信号索引
member_index = rmeta-findSignal( member, TRUE );
if ( member_index0 ) {
// normalize and retry
nw_member = qt_rmWS(member);
// remove whitespace
member = nw_member;
member_index = rmeta-findSignal( member, TRUE );
}
break;
}
/ 如果接收对象不存在相应的信号或槽,则退出
if ( member_index0) {
return FALSE;
}
// 检查连接的参数 ( 发送的信号,接收对象,处理信号的槽或信号 )
if ( !s-checkConnectArgs(signal,receiver,member) ) {
return FALSE;
} else {
// 获取处理信号的元数据对象
const QMetaData *rm = membcode == QSLOT_CODE ?
rmeta-slot( member_index, TRUE ) :
rmeta-signal( member_index, TRUE );
if ( rm ) {
// 建立连接
//( 发送信号的对象,信号的索引,接收信号的对象,
处理信号的类型,处理信号的索引 )
connectInternal( sender, signal_index, receiver, membcode, member_index );
}
}
return TRUE;
}
② 阶段
// 建立连接
//( 发送信号的对象,信号的索引,接收信号的对象,处理信号的类型,处理信号的索引 )
void QObject::connectInternal( const QObject *sender, int signal_index,
const QObject *receiver,
int membcode, int member_index )
{
// 发送信号的对象
QObject *s = (QObject*)sender;
// 接收信号的对象
QObject *r = (QObject*)receiver;
// 如果发送对象的连接查询表为 null ,则建立
if ( !s-connections ) {
// create connections lookup table
s-connections = new QSignalVec( signal_index 1 );
Q_CHECK_PTR( s-connections );
s-connections-setAutoDelete( TRUE );
}
// 获取发送对象的相应信号的连接列表
QConnectionList *clist = s-connections-at( signal_index );
if ( !clist ) {
// create receiver list
clist = new QConnectionList;
Q_CHECK_PTR( clist );
clist-setAutoDelete( TRUE );
s-connections-insert( signal_index, clist );
}
QMetaObject *rmeta = r-metaObject();
const QMetaData *rm = 0;
switch ( membcode ) {
// get receiver member
case QSLOT_CODE:
rm = rmeta-slot( member_index, TRUE );
break;
case QSIGNAL_CODE:
rm = rmeta-signal( member_index, TRUE );
break;
}
// 建立连接
QConnection *c = new QConnection( r, member_index, rm ? rm-name :
\"qt_invoke\", membcode );
Q_CHECK_PTR( c );
// 把连接添加到发送对象的连接列表中
clist-append( c );
// 判断接收对象的发送对象列表是否为 null
if ( !r-senderObjects )
// create list of senders
{
// 建立接收对象的发送对象列表
r-senderObjects = new QSenderObjectList;
}
// 把发送对象添加到发送对象列表中
r-senderObjects-append( s );
// add sender to list
}
( 2 )信号发生时激活的操作函数
接口:
/***************************************************************
** 激活 slot 的方法
****************************************************************/
void QObject::activate_signal( int signal )
{
#ifndef QT_NO_PRELIMINARY_SIGNAL_SPY
if ( qt_preliminary_signal_spy ) {
// 信号没有被阻塞
// 信号 =0
// 连接列表不为空,或者信号对应的连接存在
if ( !signalsBlocked() = 0 at( signal ) ) ) {
//
QUObject o[1];
qt_spy_signal( this, signal, o );
return;
}
}
#endif
if ( !connections || signalsBlocked() || signal0 )
return;
// 获取信号对应的连接列表
QConnectionList *clist = connections-at( signal );
if ( !clist )
return;
QUObject o[1];
//
activate_signal( clist, o );
}
/***************************************************************
** 激活 slot 的方法
****************************************************************/
void QObject::activate_signal( QConnectionList *clist, QUObject *o )
{
if ( !clist )
return;
#ifndef QT_NO_PRELIMINARY_SIGNAL_SPY
if ( qt_preliminary_signal_spy )
qt_spy_signal( this, connections-findRef( clist), o );
#endif
QObject *object;
// 发送对象列表
QSenderObjectList* sol;
// 旧的发送对象
QObject* oldSender = 0;
// 连接
QConnection *c;
if ( clist-count() == 1 ) { // save iterator
// 获取连接
c = clist-first();
//
object = c-object();
// 获取发送对象列表
sol = object-senderObjects;
if ( sol ) {
// 获取旧的发送对象
oldSender = sol-currentSender;
//
sol-ref();
// 设置新的发送对象
sol-currentSender = this;
}
if ( c-memberType() == QSIGNAL_CODE )// 如果是信号,则发送出去
object-qt_emit( c-member(), o );
else
object-qt_invoke( c-member(), o );// 如果是槽,则执行
//
if ( sol ) {
// 设置恢复为旧的发送对象
sol-currentSender = oldSender;
if ( sol-deref() )
delete sol;
}
} else {
QConnection *cd = 0;
QConnectionListIt it(*clist);
while ( (c=it.current()) ) {
it;
if ( c == cd )
continue;
cd = c;
object = c-object();
// 操作前设置当前发送对象
sol = object-senderObjects;
if ( sol ) {
oldSender = sol-currentSender;
sol-ref();
sol-currentSender = this;
}
// 如果是信号,则发送出去
if ( c-memberType() == QSIGNAL_CODE ){
object-qt_emit( c-member(), o );
}
// 如果是槽,则执行
else{
object-qt_invoke( c-member(), o );
}
// 操作后恢复当前发送对象
if (sol ) {
sol-currentSender = oldSender;
if ( sol-deref() )
delete sol;
}
}
}
} |