2010-03-04 19 views
9

मेरे पास पृष्ठभूमि थ्रेड है और थ्रेड यूआई को अपडेट करने के कुछ तरीकों को कॉल करता है (प्रगति सलाखों को दिखाने के लिए और टेक्स्ट क्षेत्रों में अतिरिक्त जानकारी दिखाने के लिए)।क्यूटी: पृष्ठभूमि थ्रेड रीफ्रेशिंग यूआई थ्रेड

यदि मैं कुछ यूआई विजेट मान संशोधित करता हूं, तो "एक अलग थ्रेड के स्वामित्व वाले ऑब्जेक्ट्स पर ईवेंट नहीं भेज सकता" दावा त्रुटि उठाई जाती है।

फ़ोरम देख रहे हैं, मैंने पढ़ा है कि मैं QMetaObject :: invokeMethod विधि का उपयोग कर सकता हूं लेकिन यह केवल काम करता है अगर मैं इसे Qt :: DirectConnection ध्वज पास करता हूं जो वास्तव में ऊपर दिखाए गए एक ही त्रुटि को उठाता है।

यदि मैं Qt :: QueuedConnection या Qt :: AutoConnection का उपयोग करता हूं, तो invokeMethod गलत लौटाता है।

मेरे कोड इस जैसा दिखता है:

ज:

class A : public QMainWindow 
{ 
    Q_OBJECT 

    QProgressBar* pb; 

    public slots: 
    bool m(bool, int); 
}; 

class B 
{ 
    A* a; 

    public: 
    void handleEvent(); 
}; 


.cpp: 

bool A::m(bool x, int y) 
{ 
    pb->setValue(y); 
    return x; 
} 

void B::handleEvent() 
{ 
    //a->m(true, 12); //raises an assertion error 

    bool r; 
    //bool ret = QMetaObject::invokeMethod(a, "m", Qt::DirectConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //raises the same assertion error error 

    bool ret = QMetaObject::invokeMethod(a, "m", Qt::AutoConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //is ignored and ret contains false. 
} 

तुम्हें पता है क्या हो रहा है या मैं गलत क्या कर रहा हूँ है? या शायद, क्या कोई मेरी नौसिखिया समस्या से निपटने के लिए मुझे एक और दृष्टिकोण सुझा सकता है?

अग्रिम धन्यवाद,

अर्नेस्टो

उत्तर

10

मैं invokeMethod() अपने आप उपयोग नहीं किया है, लेकिन ऐसा करने के लिए, मैं आम तौर पर सिर्फ संकेतों और स्लॉट का उपयोग करें। उदाहरण के लिए, आप class B के एक सदस्य है कि class A में स्लॉट से जुड़ा है कि प्रगति को अद्यतन करता के रूप में एक संकेत बना सकते हैं:

class B : public QObject 
{ 
    Q_OBJECT 

    A* a; 

signals: 
    void update_signal(bool, int); 

public: 
    void handleEvent(); 
}; 

B::B() 
{ 
    //assuming a already points to the correct place... 
    connect(this, SIGNAL(update_signal(bool,int), 
      a, SLOT(m(bool,int)), Qt::QueuedConnection); 
} 

void B::handleEvent() 
{ 
    emit update_signal(true, 12); 
} 

A::m() इस मामले में शून्य लौटने के लिए होगा, लेकिन ऐसा इसलिए है क्योंकि जब एक समस्या नहीं है एक कतारबद्ध कनेक्शन का उपयोग करके, आप किसी भी तरह से रिटर्न वैल्यू नहीं प्राप्त कर सकते क्योंकि कॉल एसिंक्रोनस है (emit update_signal(true,12) स्लॉट फ़ंक्शन को रिटर्न वैल्यू तैयार करने के लिए असंभव बनाकर कॉल कर सकता है)।

आप वास्तव में इस संबंध कहीं भी रूप में लंबे समय प्रदर्शन कर सकते हैं के रूप में आप प्रकार A का एक उद्देश्य और प्रकार B की एक वस्तु की ओर इशारा किया है। यह संकेतों और स्लॉट को बहुत लचीला बनाता है क्योंकि आप B से पूरी तरह से A को कम कर सकते हैं, फिर भी उन्हें सिग्नल और स्लॉट के माध्यम से संवाद करने की अनुमति मिलती है। उदाहरण के लिए:

class B : public QObject 
{ 
    Q_OBJECT 

signals: 
    void update_signal(bool, int); 

public: 
    void handleEvent(); 
}; 

void B::handleEvent() 
{ 
    emit update_signal(true, 12); 
} 

class A : public QMainWindow 
{ 
    Q_OBJECT 

    QProgressBar* pb; 

    public slots: 
     void m(bool, int); 
}; 

void A::m(bool x, int y) 
{ 
    pb->setValue(y); 
} 

int main() 
{ 
    A* a = new A(); 
    B* b = new B(); 

    QObject::connect(b, SIGNAL(update_signal(bool, int)), 
      a, SLOT(m(bool, int)), Qt::QueuedConnection); 

    //... 
} 

इस मामले में, b एक सूचक की दुकान या a बारे में कुछ पता नहीं है फिर भी वे एक पतली अच्छी तरह से परिभाषित चैनल के माध्यम से संवाद कर सकते हैं।

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