3 回答

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