3 回答

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超8個贊
有一些規(guī)則可以簡化信號和插槽的使用壽命,并涵蓋連接缺陷的最常見原因。如果我忘記了什么請告訴我。
1)檢查調(diào)試控制臺輸出:
發(fā)生執(zhí)行錯誤時,調(diào)試輸出可以顯示原因。
2)使用信號和插槽的完整簽名:
代替
connect(that, SIGNAL(mySignal), this, SLOT(mySlot));
寫
connect(that, SIGNAL(mySignal(int)), this, SLOT(mySlot(int)));
并檢查你的拼寫和大小寫。
3)使用現(xiàn)有的重載:
仔細(xì)檢查您是否正在使用所需的信號和插槽過載以及您使用的過載是否確實(shí)存在。
4)您的信號和插槽必須兼容:
這尤其意味著參數(shù)必須是相同類型(可以容忍引用)并且具有相同的順序。
編譯時語法也需要相同數(shù)量的參數(shù)。舊運(yùn)行時語法允許將信號連接到具有較少參數(shù)的插槽。
5)經(jīng)常檢查連接方法的返回值(程序員應(yīng)該永遠(yuǎn)不會忽略返回值):
代替
connect(that, SIGNAL(mySignal(int)), this, SLOT(mySlot(int)));
總是使用類似的東西
bool success = connect(that, SIGNAL(mySignal(int)), this, SLOT(mySlot(int)));Q_ASSERT(success);
或者,如果您喜歡拋出異?;?qū)崿F(xiàn)完整的錯誤處理。您也可以使用這樣的宏:
#ifndef QT_NO_DEBUG#define CHECK_TRUE(instruction) Q_ASSERT(instruction)#else#define CHECK_TRUE(instruction) (instruction)#endif CHECK_TRUE(connect(that, SIGNAL(mySignal(int)), this, SLOT(mySlot(int))));
6)您需要一個排隊(duì)連接的事件循環(huán):
即,當(dāng)你連接不同線程擁有的兩個對象的信號/槽(所謂的排隊(duì)連接)時,你需要exec();
在槽的線程中調(diào)用!
事件循環(huán)也需要實(shí)際提供。每當(dāng)插槽的線程卡在某種繁忙的循環(huán)中時,就不會執(zhí)行排隊(duì)的連接!
7)您需要為排隊(duì)連接注冊自定義類型:
因此,在排隊(duì)連接中使用自定義類型時,必須為此目的注冊它們。
首先使用以下宏聲明類型:
Q_DECLARE_METATYPE(MyType)
然后使用以下調(diào)用之一:
qRegisterMetaType<MyTypedefType>("MyTypedefType"); // For typedef defined typesqRegisterMetaType<MyType>(); // For other types
8)優(yōu)先于舊的運(yùn)行時檢查語法的新編譯時語法:
代替
connect(that, SIGNAL(mySignal(int)), this, SLOT(mySlot(int)));
使用這種語法
connect(that, &ThatObject::mySignal, this, &ThisObject::mySlot));
它在編譯期間檢查信號和插槽,甚至不需要目的地是實(shí)際的插槽。
如果信號過載,請使用以下語法:
connect(that, static_cast<void (ThatObject::*)(int)> &ThatObject::mySignal), this, &ThisObject::mySlot); // <Qt5.7connect(that, qOverload<int>::of(&ThatObject::mySignal), this, &ThisObject::mySlot); // >=Qt5.7 & C++11connect(that, qOverload<int>(&ThatObject::mySignal), this, &ThisObject::mySlot); // >=Qt5.7 & C++14
也不要為該語法混合const / non-const信號/槽(通常信號和槽將是非const)。
9)你的類需要一個Q_OBJECT宏:
在使用“信號”和“插槽”規(guī)范的類中,您需要添加一個Q_OBJECT宏,如下所示:
class SomeClass{ Q_OBJECT signals: void MySignal(int x);};class SomeMoreClass{ Q_OBJECTpublic slots: void MySlot(int x);};
該宏將必要的元信息添加到類中。
10)你的物品必須活著:
一旦發(fā)送方對象或接收方對象被破壞,Qt就會自動丟棄該連接。
如果未發(fā)出信號:發(fā)件人對象是否仍然存在?如果未調(diào)用插槽:接收器對象是否仍然存在?
要檢查兩個對象的生命周期,請?jiān)跇?gòu)造函數(shù)/析構(gòu)函數(shù)中使用調(diào)試器斷點(diǎn)或某些qDebug()輸出。
11)它仍然不起作用:
對你的連接做一個非??焖俸团K的檢查,你自己使用一些偽參數(shù)發(fā)出信號,看看它是否被調(diào)用:
connect(that, SIGNAL(mySignal(int)), this, SLOT(mySlot(int)));emit that->mySignal(0); // Ugly, don't forget to remove it immediately
最后,當(dāng)然可能不會發(fā)出信號。如果您遵循上述規(guī)則,那么您的程序邏輯可能出現(xiàn)問題。閱讀文檔。使用調(diào)試器。如果現(xiàn)在有其他方式,請?jiān)趕tackoverflow上詢問。
添加回答
舉報(bào)