45fan.com - 路饭网

搜索: 您的位置主页 > 网络频道 > 阅读资讯:QT中关于信号与槽机制的实现原理是什么?

QT中关于信号与槽机制的实现原理是什么?

2016-08-26 17:15:55 来源:www.45fan.com 【

QT中关于信号与槽机制的实现原理是什么?

[QT中关于信号与槽机制的实现原理.]

[tan.zhenhua]

一:[每个对象]都有一个相应的纪录该对象的[元对象]

关于元对象的类:

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;

//所有槽名字的列表

QStrList slotNames( bool super = FALSE ) const;

//所有信号名字的列表

QStrList signalNames( 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 bool connect( 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 bool disconnect( 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_index < 0 ) { // 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_index < 0 ) { // 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_index < 0 ) { // 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_index < 0 ) { // normalize and retry

nw_member = qt_rmWS(member); // remove whitespace

member = nw_member;

member_index = rmeta->findSignal( member, TRUE );

}

break;

}

/如果接收对象不存在相应的信号或槽,则退出

if ( member_index < 0 ) {

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

 


本文地址:http://www.45fan.com/a/question/68029.html
Tags: 信号 关于 机制
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部