2015-09-16 25 views
5

मैं (अर्थात बॉयलरप्लेट कोड का भार से छुटकारा पाने के) QObject आवरण वर्गों है कि अन्य QObject व्युत्पन्न वर्ग की संपत्ति का उपयोग आगे के निर्माण को आसान बनाने की कोशिश कर रहा हूँ बनाने के लिए एक मैक्रो का उपयोग करना।QObject व्युत्पन्न वर्ग

छोटे शुरू करने के लिए, मैं सिर्फ एक संपत्ति के साथ यह कोशिश कर रहा हूँ:

// Sy_test.h - The wrapped class 
class Sy_test : public QObject 
{ 
    Q_OBJECT 
    Q_PROPERTY(bool prop READ getProp WRITE setProp NOTIFY propChanged) 

public: 
    Sy_test(QObject* parent = nullptr) : 
     QObject{ parent }, 
     prop_{ false } {} 

    bool getProp() const { return prop_; } 

public slots: 
    void setProp(bool value) 
    { 
     if (value != prop_) { 
      prop_ = value; 
      emit propChanged(prop_); 
     } 
    } 

signals: 
    void propChanged(bool value); 

private: 
    bool prop_; 
}; 

// Sy_proxy.h - The wrapper generator 
#define SY_PROXYPROPERTY(Type, Name, Getter, Setter, Notifier)\ 
private:\ 
    Q_PROPERTY(Type Name READ Getter WRITE Setter NOTIFY Notifier)\ 
\ 
public:\ 
    Type Getter() const { return target_->Getter(); }\ 
\ 
public slots:\ 
    void Setter(Type value) { target_->Setter(value); }\ 
\ 
signals:\ 
    void Notifier(Type value);\ 
\ 
private:\ 
    void setConnection()\ 
    {\ 
     connect(target_, &std::remove_pointer< decltype(target_) >::type::Notifier,\ 
       this, &std::remove_pointer< decltype(this ) >::type::Notifier);\ 
    } 

#define SY_PROXY(ProxyName, TargetType, Prop1)\ 
class ProxyName : public QObject\ 
{\ 
    Q_OBJECT \ 
    Prop1 \ 
\ 
public:\ 
    ProxyName(TargetType* target) :\ 
     target_{ target }\ 
    {\ 
     setConnection();\ 
    }\ 
\ 
    virtual ~ProxyName() {}\ 
\ 
private:\ 
    TargetType* target_;\ 
}; 

// This should create a Sy_test wrapper class called Sy_testProxy 
SY_PROXY(Sy_testProxy, 
      Sy_test, 
      SY_PROXYPROPERTY(bool, prop, getProp, setProp, propChanged)) 

तो SY_PROXY मैक्रो एक वर्ग कार्यान्वयन के साथ Sy_test::prop संपत्ति की एक प्रति किया जाता है कि Sy_testProxy बुलाया बनाना चाहिए कि सिर्फ आगे अनुरोध/संकेत है।

और यह लगभग करता है। प्री-प्रोप्रोसेसर आउटपुट को देखकर (मैं g ++ का उपयोग कर रहा हूं, इसलिए .ii फाइलें), मैं Sy_testProxy क्लास का निर्माण कर सकता हूं और यह Sy_test वर्ग के समान रूप में है। हालांकि, मैं कोई त्रुटि मिलती है:

../CppTest/Sy_proxy.h:47: Error: NOTIFY signal 'propChanged' of property 'prop' does not exist in class Sy_testProxy. 
make: *** [moc_Sy_proxy.cpp] Error 1 

तो moc की तरह मेरे मैक्रो जादू पार्स करने के लिए विफल हो रहा है यह लग रहा है; हालांकि मुझे यकीन नहीं है कि SY_PROXY मैक्रो मौजूद है (Sy_testProxy नामक कक्षा से त्रुटि आ रही है), और SY_PROXYPROPERTY भी मान्य होना चाहिए (moc ने Q_PROPERTY मैक्रो से इसे पढ़ना होगा)। क्या कोई देख सकता है कि मैं गलत कहां गया हूं?

रिकॉर्ड के लिए: मैं हर किसी की तरह मैक्रो नफरत है, लेकिन मैं moc के टेम्पलेट्स के लिए घृणा और QObject आभासी विरासत की वजह से उन्हें प्रयोग में गिर गई है। यह जांच ट्रिगर हुई क्योंकि मेरे पास अलग-अलग धागे में भारी गणना करने वाले उदाहरणों का संग्रह था, लेकिन वे क्यूएमएल प्रस्तुतिकरण चलाते थे। हालांकि QML मुख्य थ्रेड के बाहर ऑब्जेक्ट्स के लिए कनेक्शन/प्रॉपर्टी बाइंडिंग की इजाजत नहीं देता है, इसलिए मुझे मुख्य थ्रेड में रहने वाली प्रॉक्सी ऑब्जेक्ट बनाने में मजबूर होना पड़ा है। अगर किसी के पास एक बेहतर विचार है, तो मैं उनके लिए बहुत खुला हूं!

+0

मुझे लगता है कि यह कुछ भी नहीं बदलता है, लेकिन आप '' मैक्रो signals' ... AFAIK MOC का विस्तार नहीं करता है के बजाय Q_SIGNAL' बहुत अच्छी तरह से कोशिश कर सकते। यह कुछ हद तक करता है, लेकिन चूंकि यह मानक से चिपकता नहीं है, इसलिए मैं हमेशा उन्हें QObject व्युत्पन्न कक्षाओं के शीर्षकों से बचाता हूं। – leemes

+0

यह मुझे एक्स-वाई समस्या की तरह लगता है। आपके प्रश्न का पहला पैराग्राफ अधिक विस्तृत होना चाहिए। कृपया बताएं कि आप वास्तव में क्या करने की कोशिश कर रहे हैं। आपकी कक्षा पदानुक्रम क्या है, किस वस्तु में गुण हैं, टेम्पलेट वर्ग कहां हैं, और आपको यह सब क्यों चाहिए। "रिकॉर्ड के लिए" पैराग्राफ इसका एक हिस्सा है, लेकिन फिर भी पर्याप्त जानकारी प्रदान नहीं करता है। –

+0

मुझे यह भी यकीन नहीं है कि "क्यूएमएल मुख्य स्रोत के बाहर ऑब्जेक्ट्स के लिए कनेक्शन/प्रॉपर्टी बाइंडिंग की इजाजत नहीं देता है" –

उत्तर

4

moc मैक्रोज़ को बहुत अच्छी तरह पसंद नहीं है। यह उन्हें कुछ हद तक फैलाता है, लेकिन जटिल होने पर यह विफल रहता है।

आप public: ², andtell MOC है कि आप समारोह समारोह घोषणा के सामने Q_SIGNAL रख कर एक संकेत होना चाहते हैं (अर्थात मैन्युअल signals मैक्रो का विस्तार) के साथ signals: को बदलने के लिए कोशिश कर सकते हैं।

बदलें

signals:\ 
    void Notifier(Type value);\ 

साथ

public:\ 
    Q_SIGNAL void Notifier(Type value);\ 

¹: जटिल के कुछ परिभाषा के लिए ... मैं जब यह विफल पता नहीं है, लेकिन मैं कुछ अलग पीआर में भाग गया अतीत में oblems। मेरे अनुभव से मेरा अनुमान है कि मोक में समस्याएं होती हैं जब मैक्रो बॉडी में एक और मैक्रो होता है, जैसे कि signals आपके उदाहरण में। लेकिन यह सिर्फ एक अनुमान है - हो सकता है कि मैक्रोज़ मॉक का प्रकार कुछ और विफल हो।

²: क्यूटी 5, कि protected हुआ करता था पहले।

+0

इसके लिए धन्यवाद! मैं सोच रहा था कि मैं सिग्नल उत्पन्न करने के लिए मैक्रोज़ का उपयोग कैसे कर सकता हूं, और इसे करने का स्पष्ट तरीका बस काम नहीं करता है। – GuyGizmo

0

moc की अनियमितताएं, आपका रैपर थ्रेड-सुरक्षित नहीं है। संपत्ति गेटटर को सही धागे से नहीं बुलाया जाता है। तो मुझे रैपर का कोई बिंदु नहीं दिख रहा है। आप सीधे क्यूएमएल से लिपटे वर्ग का उपयोग कर सकते हैं, रैपर नहीं।

थ्रेड-सुरक्षित होने के लिए, आपका रैपर लपेटा हुआ संपत्ति के मूल्य को कैश करना चाहिए, ताकि पढ़ना हमेशा स्थानीय प्रतिलिपि से हो।

उस बिंदु पर आप एक पूरी तरह से गतिशील रैपर लिख सकते हैं जो थ्रेड-सुरक्षित रूप से लिपटे ऑब्जेक्ट से गुणों को सुरक्षित रूप से आगे बढ़ा सकता है। मेटाबोजेक्ट सिस्टम का उपयोग करके आप फ्लाई पर सबकुछ उत्पन्न कर सकते हैं - संपत्ति मूल्यों की प्रतियां इत्यादि। जहां तक ​​संपत्तियां जाती हैं, आप संपूर्ण बाइनरी डिस्क्रिप्टर की प्रतिलिपि बना सकते हैं क्योंकि आपके रैपर में समान गुण होने का नाटक होता है।

+0

'Sy_test' मैक्रोज़ के साथ प्रयोग करने के लिए सिर्फ उदाहरण कोड है, इस थ्रेडसेफ में से नहीं, और न ही इसका मतलब था। मैंने पहले ही प्रॉक्सी लिखा है जो सभी गुणों, 'Q_INVOKABLE' विधियों और सार्वजनिक स्लॉट को पूरी तरह से आगे बढ़ाता है - लेकिन इस अभ्यास का पूरा बिंदु उस संबंधित बॉयलर प्लेट को कम करना था। – cmannett85

+0

@ cmannett85 आपको एक प्रॉक्सी क्लास की आवश्यकता है जो किसी अन्य वर्ग से आगे बढ़ सकती है। एक सार्वभौमिक :) ठीक है, चुनौती स्वीकार कर लिया गया। –

0

कोड का एक उत्कृष्ट टुकड़ा है, आप qmltricks के लिए Google पर जा सकते हैं, इसमें अच्छी शुरुआत के रूप में आपको जो कुछ भी चाहिए, वह सब कुछ है।

आपको केवल एक ही शीर्षक की आवश्यकता होगी। केवल गुणों या कस्टम गेटर्स/सेटर्स को पढ़ने के लिए विस्तार के लिए एक कमरा है .. लेकिन मैं एक नजर डालने का सुझाव दूंगा। मुझे अब एक मूल पृष्ठ नहीं मिला, आखिरी क्यूटी शिखर सम्मेलन पर एक प्रेजेंटेशन देखा, आप शायद हाथों पर सामग्री के लिए क्यूटी साइट देख सकते हैं।

एक जिथब पर एक लिंक के नीचे, उपलब्ध कई संस्करण हैं।

https://github.com/Cavewhere/lib-qt-qml-tricks/blob/master/include/QQmlHelpers

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