转载--QT QObject::connect函数的学习

信号和槽机制是 Qt 的核心机制,可以让编程人员将互不相关的对象绑定在一起,实现对象之间的通信。

  • 信号

当对象改变其状态时,信号就由该对象发射 (emit) 出去,而且对象只负责发送信号,它不知道另一端是谁在接收这个信号。这样就做到了真正的信息封装,能确保对象被当作一个真正的软件组件来使用。

用于接收信号,而且槽只是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且对象并不了解具体的通信机制。

  • 信号与槽的连接

所有从 QObject 或其子类 ( 例如 Qwidget ) 派生的类都能够包含信号和槽。因为信号与槽的连接是通过 QObject 的 connect() 成员函数来实现的。

connect(sender, SIGNAL(signal), receiver, SLOT(slot));

其中 sender 与 receiver 是指向对象的指针,SIGNAL() 与 SLOT() 是转换信号与槽的宏。

 

Qobject(QObject.h)源码中可以看到QObject::connect的定义是这样的:

connect(const QObject *sender, const char *signal,  
                    const QObject *receiver, const char *member, Qt::ConnectionType =  
    #ifdef qdoc  
                        Qt::AutoConnection  
    #else  
        #ifdef QT3_SUPPORT  
                            Qt::AutoCompatConnection  
    #else  
                                Qt::AutoConnection  
        #endif  
    #endif  
    );  
inline bool connect(const QObject *sender, const char *signal,  
                    const char *member, Qt::ConnectionType type =  
    #ifdef qdoc  
                     Qt::AutoConnection  
    #else  
        #ifdef QT3_SUPPORT  
                                Qt::AutoCompatConnection  
        #else  
                                Qt::AutoConnection  
        #endif  
    #endif  
    ) const;  

在QObject.cpp文件中可以找到connect的实现代码

 QObject::connect(const QObject *sender, const char *signal,  
                      const QObject *receiver, const char *method,  
                      Qt::ConnectionType type)  
{  
    {  
        const void *cbdata[] = { sender, signal, receiver, method, &type };  
        if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))  
            return true;  
    }  
  
    if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {  
        qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",  
                 sender ? sender->metaObject()->className() : "(null)",  
                 (signal && *signal) ? signal+1 : "(null)",  
                 receiver ? receiver->metaObject()->className() : "(null)",  
                 (method && *method) ? method+1 : "(null)");  
        return false;  
    }  
    QByteArray tmp_signal_name;  
  
    if (!check_signal_macro(sender, signal, "connect", "bind"))  
        return false;  
    const QMetaObject *smeta = sender->metaObject();  
    const char *signal_arg = signal;  
    ++signal; //skip code  
    int signal_index = smeta->indexOfSignal(signal);  
    if (signal_index < 0) {  
        // check for normalized signatures  
        tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);  
        signal = tmp_signal_name.constData() + 1;  
  
        signal_index = smeta->indexOfSignal(signal);  
        if (signal_index < 0) {  
            err_method_notfound(sender, signal_arg, "connect");  
            err_info_about_objects("connect", sender, receiver);  
            return false;  
        }  
    }  
  
    QByteArray tmp_method_name;  
    int membcode = extract_code(method);  
  
    if (!check_method_code(membcode, receiver, method, "connect"))  
        return false;  
    const char *method_arg = method;  
    ++method; // skip code  
  
    const QMetaObject *rmeta = receiver->metaObject();  
    int method_index = -1;  
    switch (membcode) {  
    case QSLOT_CODE:  
        method_index = rmeta->indexOfSlot(method);  
        break;  
    case QSIGNAL_CODE:  
        method_index = rmeta->indexOfSignal(method);  
        break;  
    }  
    if (method_index < 0) {  
        // check for normalized methods  
        tmp_method_name = QMetaObject::normalizedSignature(method);  
        method = tmp_method_name.constData();  
        switch (membcode) {  
        case QSLOT_CODE:  
            method_index = rmeta->indexOfSlot(method);  
            break;  
        case QSIGNAL_CODE:  
            method_index = rmeta->indexOfSignal(method);  
            break;  
        }  
    }  
  
    if (method_index < 0) {  
        err_method_notfound(receiver, method_arg, "connect");  
        err_info_about_objects("connect", sender, receiver);  
        return false;  
    }  
    if (!QMetaObject::checkConnectArgs(signal, method)) {  
        qWarning("QObject::connect: Incompatible sender/receiver arguments"  
                 "\n        %s::%s --> %s::%s",  
                 sender->metaObject()->className(), signal,  
                 receiver->metaObject()->className(), method);  
        return false;  
    }  
  
    int *types = 0;  
    if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)  
            && !(types = queuedConnectionTypes(smeta->method(signal_index).parameterTypes())))  
        return false;  
  
    QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);  
    const_cast<QObject*>(sender)->connectNotify(signal - 1);  
    return true;  
}  

 

posted @ 2017-06-06 09:47  vidahaha  阅读(6005)  评论(0编辑  收藏  举报