自定義信號(hào)槽
//!!! Qt5
#include <QObject>
////////// newspaper.h
class Newspaper : public QObject
{
Q_OBJECT
public:
Newspaper(const QString & name) :
m_name(name)
{
}
void send()
{
emit newPaper(m_name);
}
signals:
void newPaper(const QString &name);
private:
QString m_name;
};
////////// reader.h
#include <QObject>
#include <QDebug>
class Reader : public QObject
{
Q_OBJECT
public:
Reader() {}
void receiveNewspaper(const QString & name)
{
qDebug() << "Receives Newspaper: " << name;
}
};
////////// main.cpp
#include <QCoreApplication>
#include "newspaper.h"
#include "reader.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Newspaper newspaper("Newspaper A");
Reader reader;
QObject::connect(&newspaper, &Newspaper::newPaper,
&reader, &Reader::receiveNewspaper);
newspaper.send();
return app.exec();
}
關(guān)于Q_OBJECT宏
只有繼承了QObject類的類枫攀,才具有信號(hào)槽的能力偎快。所以禽笑,為了使用信號(hào)槽,必須繼承QObject蛤奥。
凡是QObject類(不管是直接子類還是間接子類)佳镜,都應(yīng)該在第一行代碼寫上Q_OBJECT。不管是不是使用信號(hào)槽凡桥,都應(yīng)該添加這個(gè)宏蟀伸。這個(gè)宏的展開將為我們的類提供信號(hào)槽機(jī)制、國際化機(jī)制以及 Qt 提供的不基于 C++ RTTI 的反射能力缅刽。因此啊掏,如果你覺得你的類不需要使用信號(hào)槽,就不添加這個(gè)宏衰猛,就是錯(cuò)誤的迟蜜。其它很多操作都會(huì)依賴于這個(gè)宏。
注意啡省,這個(gè)宏將由 moc(我們會(huì)在后面章節(jié)中介紹 moc娜睛。這里你可以將其理解為一種預(yù)處理器,是比 C++ 預(yù)處理器更早執(zhí)行的預(yù)處理器卦睹。) 做特殊處理畦戒,不僅僅是宏展開這么簡單。moc 會(huì)讀取標(biāo)記了 Q_OBJECT 的頭文件分预,生成以 moc_ 為前綴的文件兢交,比如 newspaper.h 將生成 moc_newspaper.cpp。你可以到構(gòu)建目錄查看這個(gè)文件笼痹,看看到底增加了什么內(nèi)容配喳。
注意,由于 moc 只處理頭文件中的標(biāo)記了Q_OBJECT的類聲明凳干,不會(huì)處理 cpp 文件中的類似聲明晴裹。因此,如果我們的Newspaper和Reader類位于 main.cpp 中救赐,是無法得到 moc 的處理的涧团。解決方法是,我們手動(dòng)調(diào)用 moc 工具處理 main.cpp经磅,并且將 main.cpp 中的#include "newspaper.h"改為#include "moc_newspaper.h"就可以了泌绣。不過,這是相當(dāng)繁瑣的步驟预厌,為了避免這樣修改阿迈,我們還是將其放在頭文件中。許多初學(xué)者會(huì)遇到莫名其妙的錯(cuò)誤轧叽,一加上Q_OBJECT就出錯(cuò)苗沧,很大一部分是因?yàn)闆]有注意到這個(gè)宏應(yīng)該放在頭文件中刊棕。
總結(jié)一下自定義信號(hào)槽需要注意的事項(xiàng):
- 發(fā)送者和接收者都需要是QObject的子類(當(dāng)然,槽函數(shù)是全局函數(shù)待逞、Lambda 表達(dá)式等無需接收者的時(shí)候除外)
- 使用 signals 標(biāo)記信號(hào)函數(shù)甥角,信號(hào)是一個(gè)函數(shù)聲明,返回 void识樱,不需要實(shí)現(xiàn)函數(shù)代碼
- 槽函數(shù)是普通的成員函數(shù)嗤无,作為成員函數(shù),會(huì)受到 public牺荠、private翁巍、protected 的影響
- 使用 emit 在恰當(dāng)?shù)奈恢冒l(fā)送信號(hào)
- 使用QObject::connect()函數(shù)連接信號(hào)和槽