Qt signal-slot

Qt的信号和槽机制,使得两个对象可以进行交互。得益于Qt的元对象系统,可以在Qt的help中查找The Meta-Object System,它告诉我们如何使用该系统,进而使用信号和槽以及属性系统。

来自Qt help 文档
The meta-object system is based on three things:
1.The QObject class provides a base class for objects that can take advantage of the meta-object system.
2.The Q_OBJECT macro inside the private section of the class declaration is used to enable meta-object features, such as dynamic properties, signals, and slots.
3.The Meta-Object Compiler (moc) supplies each QObject subclass with the necessary code to implement meta-object features.

我们只需要继承QObject或其子类,并使用宏Q_OBJECT,signals下声明信号,xx slots下声明槽函数即可。

使用时,我们提倡最新的语法,函数指针,而非字符串。

// 1 继承QObject
class Sender:public QObject{
    // 2 宏,元对象系统
    Q_OBJECT
public:
    explicit Sender(QObject *parent = nullptr){}
    ~Sender(){}
    void sendData(){
        emit sig_sendData(10);
        // emit 关键字为空
        sig_sendData("hello");
        Data data; data.count = 20; data.str = "good";
        emit sig_sendCusData(data);
    }
signals:
    // 重载
    void sig_sendData(int data);
    void sig_sendData(QString data);

    // 自定义数据
    void sig_sendCusData(Data &data);
};
class Geter:public QObject{
    Q_OBJECT
public:
    explicit Geter(QObject *parent = nullptr){}
    ~Geter(){}

public slots:
    void slot_getData(int data);
    void slot_getData(QString data);
    void slot_getCusData(Data &data);
private slots:

};

连接

    Sender *pSender = new Sender;
    Geter *pGeter = new Geter;

    connect(pSender, static_cast<void(Sender::*)(int)>(&Sender::sig_sendData),
            pGeter,  static_cast<void(Geter::*)(int)>(&Geter::slot_getData));
    
    // 使用自定义数据,直连可以的,但是队列时,涉及到copy等操作,需要注册到元系统中
    qRegisterMetaType<Data>("Data");
    qRegisterMetaType<Data>("Data &");
    qRegisterMetaType<Data>("Data *");
    connect(pSender, &Sender::sig_sendCusData, pGeter, &Geter::slot_getCusData, Qt::QueuedConnection);
    
    // C++11 lambda
    connect(pSender, &Sender::sig_sendCusData, [](Data &data){
        // to do
    });

    // 不仅仅QObject
    auto fun = std::function<void(Data)>{
            
    };
    connect(pSender, &Sender::sig_sendCusData, fun);
  • 信号的重载,使用函数指针转换即可
  • 自定义数据类型,qRegisterMetaType<T>("Tname")
  • emit 关键字没有非常实用
  • 新语法,它可以连接QObject的任何成员方法,不仅仅是定义的槽。lambda,bind,function
  • 连接类型,默认AutoConnection。连接的类型确定时机:信号发出。判定规则:接受者所依附的线程和发送者所依附的线程是否相同,相同则直连,否则队列连。槽函数工作的线程:直连时,在信号的发送端;队列连时,在接受端。(个人认为:连接类型不应该人为修改,选择默认的就可以)
(Default) If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.

既然使用了qRegisterMetaType,顺带说下Q_DECLARE_METATYPE,这样就可使用Qt的万能数据QVariant了,单这个只是在直连时有效,因此配合qRegisterMetaType使用。

Q_DECLARE_METATYPE声明一个自定义类型时,我们要为该类声明默认构造,拷贝构造,重载等于号,析构函数。eg:

// Creating Custom Qt Types
class CusVar{
public:
    CusVar(){}
    CusVar(const CusVar &other){info = other.info;}
    ~CusVar(){}

    void operator = (const CusVar &other){
        info = other.info;
    }

    QString getInfo(){return info;}
private:
    QString info = "123";
};
Q_DECLARE_METATYPE(CusVar)
    在QVariant使用中
    
    QVariant varData;
    // default
    CusVar var;
    // copy
    varData.setValue(var);

    // default
    CusVar getVar;
    // copy =
    getVar = varData.value<CusVar>();
    qDebug() << "get cusVar" << getVar.getInfo();

    // copy
    CusVar getVarEx = varData.value<CusVar>();
    qDebug() << "get cusVarEx" << getVarEx.getInfo();

猜你喜欢

转载自blog.csdn.net/qq_39175540/article/details/85687223