2014-10-17 15 views
11

मैं बार-बार लोगों को स्लॉट के साथ समस्याएं नहीं देखता हूं। मैं कुछ सबसे आम कारणों को इकट्ठा करना चाहता हूं। तो शायद मैं लोगों की मदद कर सकता हूं और बहुत सारे अनावश्यक प्रश्नों से बच सकता हूं।मेरा सिग्नल/स्लॉट कनेक्शन काम नहीं करता

सिग्नल/स्लॉट कनेक्शन काम करने के कारण क्या हैं? ऐसी समस्याओं से कैसे बचा जा सकता है?

उत्तर

23

कुछ नियम हैं जो सिग्नल और स्लॉट के साथ जीवन को आसान बनाते हैं और दोषपूर्ण कनेक्शन के लिए सबसे आम कारण को कवर करते हैं। अगर मैं कुछ भूल गया तो कृपया मुझे बताओ।

1) संकेत और स्लॉट का पूरा हस्ताक्षर का उपयोग करें:

के बजाय

connect(that, SIGNAL(mySignal), this, SLOT(mySlot)); 

लिखने

connect(that, SIGNAL(mySignal(int)), this, SLOT(mySlot(int))); 

और अपनी वर्तनी और कैपिटलाइज़ेशन की जाँच करें।

2) का प्रयोग करें मौजूदा भार के:

carfully यदि आप संकेत और स्लॉट के वांछित भार के प्रयोग कर रहे हैं और अगर आप वास्तव में भार के लिए प्रयोग किया जाता का अस्तित्व की जाँच करें।

3) आपका संकेत और स्लॉट संगत होना चाहिए:

यह विशेष रूप से इसका मतलब है मापदंडों एक ही प्रकार का होना चाहिए (संदर्भ सहन कर रहे हैं) और एक ही आदेश है।

संकलन-समय वाक्यविन्यास को भी पैरामीटर की एक ही संख्या की आवश्यकता है। पुराना रनटाइम सिंटैक्स कम पैरामीटर के साथ स्लॉट्स को सिग्नल कनेक्ट करने की अनुमति देता है।

4) हमेशा कनेक्ट विधि (प्रोग्रामर कभी नहीं वापसी मान अनदेखा कर देना चाहिए) की वापसी के मूल्य की जाँच करें:

इसके बजाय

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)))); 

5) आप पंक्तिबद्ध कनेक्शन के लिए एक घटना पाश की जरूरत है::

यानी आप भी ऐसे ही मैक्रो का उपयोग कर सकते हैं जब भी आप अलग-अलग धागे (तथाकथित कतारबद्ध कनेक्शन) के स्वामित्व वाली दो वस्तुओं के सिग्नल/स्लॉट कनेक्ट करते हैं, तो आपको स्लॉट के धागे में exec(); पर कॉल करने की आवश्यकता होती है!

ईवेंट लूप को वास्तव में भी सेवा की आवश्यकता है। जब भी स्लॉट का धागा किसी प्रकार के व्यस्त पाश में फंस जाता है, कतारबद्ध कनेक्शन निष्पादित नहीं होते हैं!

तो जब कस्टम प्रकार का उपयोग कर पंक्तिबद्ध कनेक्शन में आप इस उद्देश्य के लिए उन्हें रजिस्टर करना होगा:

6) आप पंक्तिबद्ध कनेक्शन के लिए कस्टम प्रकार रजिस्टर की जरूरत है।

Q_DECLARE_METATYPE(MyType) 

तो निम्नलिखित कॉल का उपयोग करें::

qRegisterMetaType<MyTypedefType>("MyTypedefType"); // For typedef defined types 
qRegisterMetaType<MyType>(); // For other types 

7) नए संकलन समय वाक्य रचना पसंद करते हैं अधिक पुरानी रन-टाइम वाक्य रचना की जाँच की

पहले निम्नलिखित मैक्रो का उपयोग प्रकार की घोषणा :

के बजाय

उपयोग इस वाक्य

connect(that, &ThatObject::mySignal, this, &ThisObject::mySlot)); 

जो संकलन समय के दौरान संकेत और स्लॉट की जाँच करता है और यहां तक ​​कि एक वास्तविक स्लॉट जा रहा है गंतव्य की जरूरत नहीं है।

अपने सिग्नल उपयोग ओवरलोड हो गया है, तो निम्न सिंटैक्स:

connect(that, static_cast<void (ThatObject::*)(int)> &ThatObject::mySignal), this, &ThisObject::mySlot); // <Qt5.7 
connect(that, qOverload<int>::of(&ThatObject::mySignal), this, &ThisObject::mySlot); // >=Qt5.7 & C++11 
connect(that, qOverload<int>(&ThatObject::mySignal), this, &ThisObject::mySlot); // >=Qt5.7 & C++14 

इसके अलावा कि वाक्य रचना के लिए स्थिरांक/गैर-स्थिरांक संकेत/स्लॉट मिश्रित नहीं होते हैं (सामान्य रूप से संकेत और स्लॉट गैर स्थिरांक हो जाएगा)।

8) आपका कक्षाएं एक Q_OBJECT मैक्रो की जरूरत है:

कक्षाओं में जहां "संकेत" और "स्लॉट" विनिर्देशों आप इस प्रकार का Q_OBJECT मैक्रो जोड़ने की जरूरत का उपयोग कर रहे हैं:

class SomeClass 
{ 
    Q_OBJECT 

signals: 
    void MySignal(int x); 
}; 

class SomeMoreClass 
{ 
    Q_OBJECT 

public slots: 
    void MySlot(int x); 
}; 

यह मैक्रो कक्षा में आवश्यक मेटा जानकारी जोड़ता है।

9) आपका वस्तुओं जिंदा होना चाहिए:

जैसे ही या तो इस वस्तु या रिसीवर वस्तु नष्ट हो जाता है, क्यूटी स्वचालित रूप से कनेक्शन को छोड़ देता है।

यदि सिग्नल उत्सर्जित नहीं होता है: क्या प्रेषक ऑब्जेक्ट अभी भी मौजूद है? यदि स्लॉट नहीं कहा जाता है: क्या रिसीवर ऑब्जेक्ट अभी भी मौजूद है?

दोनों ऑब्जेक्ट्स के जीवनकाल की जांच करने के लिए कन्स्ट्रक्टर/विनाशकों में डीबगर ब्रेक पॉइंट या कुछ qDebug() आउटपुट का उपयोग करें।

10) यह अभी भी काम नहीं करता:

ऐसा करने के लिए अपने कनेक्शन की एक बहुत ही त्वरित और गंदी जाँच अपने आप से संकेत फेंकना कुछ डमी तर्कों का उपयोग करें और देखें कि यह कहा जाता है:

connect(that, SIGNAL(mySignal(int)), this, SLOT(mySlot(int))); 
emit that->mySignal(0); // Ugly, don't forget to remove it immediately 

आखिर में यह संभव है कि सिग्नल बस उत्सर्जित न हो। यदि आपने उपर्युक्त नियमों का पालन किया है, तो शायद आपके प्रोग्राम के तर्क में कुछ गलत है। दस्तावेज पढ़ें। डीबगर का प्रयोग करें।और यदि अब कोई अन्य तरीका है, तो स्टैक ओवरफ्लो से पूछें।

+0

यदि आप कतारबद्ध स्लॉट में इसका उपयोग करने की योजना बना रहे हैं तो आपको वास्तव में अपने कस्टम प्रकार को 'Q_DECLARE_METATYPE' के साथ घोषित नहीं करना है। 'qRegisterMetatype' पर्याप्त होना चाहिए। 'Q_DECLARE_METATYPE' केवल टेम्पलेट-आधारित कार्यों के लिए आवश्यक है। इस बारे में एक छोटी सी चर्चा थी [यहां] (http://stackoverflow.com/questions/23219770/how-to-register-reference-to-qt-containers/23235165#comment35552191_23235165)। – thuga

+0

एचएम। ऐसा लगता है कि QVariant कतारबद्ध कनेक्शन तंत्र का प्रत्यक्ष हिस्सा नहीं है। हालांकि qRegisterMetaType() का दस्तावेज कहता है: "इस फ़ंक्शन को टाइप करने के लिए कॉल करें T. T को Q_DECLARE_METATYPE()" के साथ घोषित किया जाना चाहिए। – Silicomancer

संबंधित मुद्दे