2012-09-18 19 views
22

मुझे वास्तव में क्यूएमएल पसंद है। मुझे पसंद है कि मैं घटकों को परिभाषित कर सकता हूं (कक्षाओं के तुलनीय) और उनके गुण, और उन्हें कहीं और (वस्तुओं के तुलनीय) से तुरंत चालू कर सकते हैं।क्यूएमएल में बाल प्लेसहोल्डर्स के साथ "टेम्पलेट" को कैसे परिभाषित किया जाए?

मैं परिभाषित कर सकता हूं, एक बटन, कुछ दिखने और महसूस करने और उस पर एक लेबल टेक्स्ट परिभाषित कर सकता हूं। ऐसा इसलिए किया जाता जा सकता है, उदाहरण के लिए, इस घटक परिभाषा (Button.qml) का उपयोग:

Item { 
    id: button 
    property string label 

    anchors.fill: parent 

    Rectangle { 
     anchors.fill: parent 
     radius: 10 
     color: "gray" 

     Text { 
      anchors.centerIn: parent 
      font.pixelSize: 20 
      text: button.label 
      color: "white" 
     } 
    } 
} 

और instanciated यह मुख्य फ़ाइल में (main.qml):

Rectangle { 
    width: 300 
    height: 200 

    Button { 
     anchors.centerIn: parent 
     anchors.margins: 50 
     label: "Hello button!" 
    } 
} 

लेकिन मैं निम्नलिखित प्रतिबंध देखें: मैं केवल यह कर सकते हैं कुछ गुण के साथ एक बटन टेम्पलेट परिभाषित करें, कुछ प्लेसहोल्डर के साथ नहीं। उदाहरण में परिभाषित सभी बच्चे प्रत्यक्ष बच्चे होंगे, कम से कम प्रति डिफ़ॉल्ट, और मैं इस व्यवहार को बदलना चाहता हूं।

मान लें कि मैं एक आइटम रखना चाहता हूं (चलो एक छवि कहें, लेकिन मैं Button की परिभाषा बताना नहीं चाहता कि यह एक छवि होगी)। मुझे कुछ ऐसा लगता है:

Item { 
    id: button 
    property Item contents <-- the client can set the placeholder content here 

    anchors.fill: parent 

    Rectangle { 
     anchors.fill: parent 
     radius: 10 
     color: "gray" 

     Item { 
      id: placeholder  <-- where the placeholder should be inserted 
     } 
    } 

    Component.onCompleted: { 
     // move the contents into the placeholder... 
    } 
} 

मैं इसे कैसे प्राप्त कर सकता हूं? मुझे नहीं पता कि Component.onCompleted का उपयोग सही तरीका है या नहीं। ध्यान दें कि, हालांकि, मेरे मामले में सामग्री बाद में कभी नहीं बदलेगी (कम से कम आवेदन के मेरे वर्तमान डिजाइन में ...)।

इसके अलावा, मैं प्लेसहोल्डर के भीतर काम करने के लिए एंकरिंग करना चाहता हूं। उदाहरण के लिए, यदि मैं सामग्री को टेक्स्ट तत्व के रूप में परिभाषित करता हूं, तो उसके माता-पिता में केंद्रित होता है (जो पहले टेम्पलेट स्वयं होगा)। फिर मेरा कोड प्लेसहोल्डर को प्लेसहोल्डर में ले जाता है और पैरेंट एंकर को प्लेसहोल्डर आइटम के रूप में होना चाहिए, न कि टेम्पलेट आइटम।

उत्तर

30

मैंने पाया एक बहुत अच्छे क्यूटी डेवलपर दिवस 2011 "Qt Quick Best Practices and Design Patterns" की प्रस्तुति में सुझाए गए इस प्रश्न का उत्तर।

वे default property alias ...उर्फ ​​ किसी आइटम की किसी भी संपत्ति के लिए बच्चे के आइटम का उपयोग करते हैं। यदि आप बच्चों को उपनाम नहीं करना चाहते हैं, लेकिन उपनाम संपत्ति को एक नाम दें, तो बस default हटा दें। (शाब्दिक बच्चों प्रति QML परिभाषा डिफ़ॉल्ट संपत्ति का मूल्य है।)

Item { 
    id: button 
    default property alias contents: placeholder.children 

    anchors.fill: parent 

    Rectangle { 
     anchors.fill: parent 
     radius: 10 
     color: "gray" 

     Item { 
      id: placeholder  <-- where the placeholder should be inserted 
     } 
    } 
} 
+0

बीटीडब्ल्यू, यदि आप अभी भी बात से क्यूएमएल स्कोप पहेली के बारे में सोच रहे हैं, तो देखें: http://stackoverflow.com/questions/11339719/qml-component-scope-puzzle – mlvljr

+1

शानदार, इस लिंक के लिए धन्यवाद!;) वैसे, "डी-पॉइंटर" (इस बात में भी) निजी सदस्यों (जेएस फंक्शंस) को छिपाने के लिए इस्तेमाल किया जा सकता है। मुझे डबल अंडरस्कोर से बेहतर लगता है। मैं यह भी सुनिश्चित करने के लिए "निजी" नाम देता हूं कि कोई भी इस बच्चे के ऑब्जेक्ट के सदस्यों को गलती से एक्सेस नहीं करेगा। – leemes

+0

दिलचस्प, याद रखें (डी-पीआरटी), तो यह कुछ प्रकार का क्यूएमएल/जेएस पिंपल है? – mlvljr

3

दरअसल, जो मैंने सुना है उससे सही उत्तर QML Loader का उपयोग करना चाहते हैं जो आप चाहते हैं।

[कहा जा रहा है; मैंने वास्तव में अभी तक यह कोशिश नहीं की है, लेकिन यह मेरी निकट अवधि की कोशिश सूची में है और काफी सीधे आगे दिखता है]

इसके अलावा, अन्य "QML Loader" प्रश्नों के लिए स्टैक ओवरफ्लो खोजें क्योंकि वहां एक संख्या है जो आपको प्रारंभ करने में मदद करेगी।

+0

धन्यवाद, यह नहीं पता था कि क्यूएमएल लोडर क्या है और यह ऐसी परिस्थितियों में मदद करता है। मैं इसे देख लूंगा। – leemes

+0

मिश के उत्तर की तरह, आपका समाधान एंकरिंग के साथ काम नहीं करता है। उदाहरण: 'लोडर {स्रोतकंपोनेंट: आयताकार {रंग:" लाल "; एंकरर्स। फिल: पैरेंट}} '। आयताकार लोडर के माता-पिता को भरना चाहिए, लेकिन ऐसा नहीं है। (यह तब तक अदृश्य है जब तक कि मैं स्पष्ट रूप से चौड़ाई और ऊंचाई निर्धारित नहीं करता हूं।) – leemes

+0

ओह, मैं लोडर को अपने माता-पिता को भरने के लिए बताना भूल गया। अब यह काम करता है, मुझे लगता है ... – leemes

1

आप आइटम (रों) स्थानांतरित कर सकते हैं कोड के इस टुकड़े का उपयोग कर (आप प्लेसहोल्डर के भीतर कई आइटम का समर्थन करना चाहते हैं):

property list<Item> contents 

Component.onCompleted: { 
    var contentItems = []; 
    for(var i = 0; i < contents.length; ++i) 
     contentItems.push(contents[i]); 
    placeholder.children = contentItems; 
} 

नोट आप के लिए आइटम की एक सूची प्रदान की जरूरत नहीं है कि सामग्रियों की संपत्ति, एकल मूल्यों के रूप में क्यूएमएल इंजन द्वारा भी सूची गुणों के लिए स्वीकार की जाएगी।

+0

हाँ, यह वस्तुओं को स्थानांतरित करने के लिए सही कोड स्निपेट प्रतीत होता है। यह काम करता है, लेकिन यह एंकरिंग का सम्मान नहीं करता है। (यदि मैं 'anchors.centerIn: parent' के साथ एक पाठ प्रदान करता हूं उदाहरण के लिए, परिणाम ऐसा लगता है कि मैंने एंकर संपत्ति सेट नहीं की है।) – leemes

+0

मुझे नहीं पता कि एंकर संपत्ति को "अपडेट" कैसे करें (शायद सामग्री आइटम अभी भी लगता है कि उनके माता-पिता टेम्पलेट हैं?) लेकिन आप सामग्री क्षेत्र को भरने के लिए उनका आकार बदल सकते हैं। बस अपनी चौड़ाई और ऊंचाई प्लेसहोल्डर के आकार में सेट करें। – Misch

1

संक्षेप में (विचार को दिखाने के लिए):

import QtQuick 1.1 

Item { 
    width: 200 
    height: 100 

    //<-- the client can set the placeholder content here 
    property Item contents: Rectangle { 
     anchors.fill: parent 
     anchors.margins: 25 
     color: "red" 
    } 

    Rectangle { 
     id: container 

     anchors.fill: parent 
     radius: 10 
     color: "gray" 

     //<-- where the placeholder should be inserted 
    } 

    Component.onCompleted: { 
     contents.parent = container 
    } 
} 

कुछ हद तक लंबे समय तक संस्करण (समर्थन सामग्री रीअसाइनमेंट):

import QtQuick 1.1 

Item { 
    width: 200 
    height: 100 

    //<-- the client can set the placeholder content here 
    property Item contents: Rectangle { 
     //anchors can be "presupplied", or set within the insertion code 
     //anchors.fill: parent 
     //anchors.margins: 25 
     color: "red" 
    } 

    Rectangle { 
     id: container 

     anchors.fill: parent 
     radius: 10 
     color: "gray" 

     //<-- where the placeholder should be inserted 
     //Item { 
     // id: placeholder 
     //} 
    } 

    //"__" means private by QML convention 
    function __insertContents() { 
     // move the contents into the placeholder... 
     contents.parent = container 
     contents.anchors.fill = container 
     contents.anchors.margins = 25 
    } 

    onContentsChanged: { 
     if (contents !== null) 
      __insertContents() 
    } 

    Component.onCompleted: { 
     __insertContents() 
    } 
} 

आशा इस मदद करता है :)

+0

यदि आपके कोई प्रश्न या अतिरिक्त आवश्यकताएं हैं, तो पूछने के लिए स्वतंत्र महसूस करें (या परिवर्तनों का अनुरोध करें) :) – mlvljr

+2

इस समाधान के लिए धन्यवाद, लेकिन मैंने कुछ दिन पहले एक क्यूटी डेवलपर डे प्रेजेंटेशन से बहुत अच्छा उद्धृत करते हुए एक और जवाब जोड़ा। – leemes

+0

हाँ, यह एक और चाल है, लेकिन इसके साथ सावधान रहें 1) आप वस्तुओं को स्थिर रूप से जोड़ने तक सीमित हैं (जब तक आप सीधे बच्चों की संपत्ति में हस्तक्षेप नहीं करते हैं, जो कि एलियासिंग के प्रारंभिक उद्देश्य को किस प्रकार पराजित करते हैं) और 2) (एक मामूली चीज़) उदाहरण विरासत QtObject (टाइमर की तरह) इस तरह से जोड़ा नहीं जा सकता है (क्योंकि बच्चे आइटम की एक सूची है, सादा QtObjects नहीं)। इसके अलावा, पुनर्विचार दृष्टिकोण का उपयोग करके, आप मनमाने ढंग से जोड़े गए आइटमों को स्थानांतरित कर सकते हैं (प्रत्येक को अपने कंटेनर में डालकर)। – mlvljr

4

Necro जवाब मामले में किसी और यहाँ अंत के रूप में मैंने किया था।

क्यूटी 5 में लाइन के साथ कहीं भी डिफ़ॉल्ट संपत्ति "data" और "बच्चों" नहीं बन गई। इससे "आइटम" की तुलना में अन्य ऑब्जेक्ट प्रकारों को जोड़ना संभव हो जाता है। उदा।

Item { 
    id: button 
    default property alias contents: placeholder.data 

    anchors.fill: parent 

    Rectangle { 
     anchors.fill: parent 
     radius: 10 
     color: "gray" 

     Item { 
      id: placeholder  <-- where the placeholder should be inserted 
     } 
    } 
} 

नोट:: placeholder.dataplaceholder.children के बजाय यह भी ध्यान रखें कृपया आप की जरूरत नहीं है कि कनेक्शन के साथ-साथ

तो Qt5 में आपको क्या करना चाहिए (ऊपर अपने ही सवाल का जवाब देने) जोड़ा जा सकता है उपनाम का नाम contents का उपयोग करने के लिए - यह आपकी पसंद की कुछ भी हो सकती है। एक उदाहरण:

Item { 
    id: button 
    default property alias foo: placeholder.data 
    ... 

} 
+0

https://stackoverflow.com/a/10031214/11722 में एक उदाहरण है जो प्लेसहोल्डर को भी जोड़ता है। – Zitrax

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