2013-07-29 10 views
11

मैं किसी ऑब्जेक्ट की वैश्विक स्थिति (या इसके पूर्वजों के सापेक्ष) को ट्रैक करना चाहता हूं और इसे किसी अन्य आइटम की स्थिति से जोड़ना चाहता हूं।क्यूएमएल - एक घटक की वैश्विक स्थिति को ट्रैक करना

मैं mapFromItem का उपयोग कर के रूप में इस के बारे में सोच रहा था: इस दृष्टिकोण के साथ

SomeObject { 
    x: ancestor.mapFromItem(trackedObject, trackedObject.x, 0).x 
    y: ancestor.mapFromItem(trackedObject, 0, trackedObject.y).y 
} 

समस्या यह है कि एक बार mapFromItem मूल्यांकन किया जाता है और के रूप में यह में से एक तर्क अद्यतन हो जाता है अद्यतन नहीं करता है। इसके अलावा मैपिंग कभी-कभी ऑफसेट द्वारा बदली गई नई स्थिति लौटाती है, मैं कोड में ट्रैक करने में असमर्थ हूं (लेकिन यह मामला हाथ में नहीं है)।

मेरा दूसरा विचार एक ऐसी क्रिया को लागू करके वैश्विक स्थिति की गणना करना था जो प्रदान किए गए पूर्वजों (calculateOffsetFrom(ancestor) जैसे कुछ) पर रोक लगाता है। फिर भी यह केवल एक कार्य है और जहां तक ​​मेरा संबंध है, इसे पूर्वजों की स्थिति में परिवर्तनों में से एक के रूप में फिर से मूल्यांकन नहीं किया जाएगा (जब तक कि उस कार्य में, मैं इसे onXChanged सिग्नल में प्रत्येक के लिए कॉल करने के लिए बाध्य करूंगा रास्ते में पूर्वजों, जो एक गंदे समाधान की तरह लगता है)। वस्तु मैं ट्रैक करने के लिए चाहते हैं और करने के लिए

तो अंत में मैं जोड़ दिया है गुण तो मैं उन्हें करने के लिए बाध्य:

TrackedObject { 
    property real offsetX: x + parent.x + parent.parent.x + parent.parent.parent.x ... 
    property real offsetY: y + parent.y + parent.parent.y + parent.parent.parent.y ... 
} 

SomeObject { 
    x: trackedObject.globalX 
    y: trackedObject.globalY 
} 

लेकिन अच्छी तरह से ... हाँ ... यह एक पर पैमाने पर नहीं है सब कुछ और बदसूरत के रूप में यह हो जाता है।

क्या किसी को पता है कि क्लीनर तरीके से इस समस्या को हल किया जा सकता है?

संपादित करें: जहां तक ​​मुझे चिंतित है मैं इस मामले में एंकर का उपयोग नहीं कर सकता। SomeObject घटक एक कस्टम घटक है जो एक बिंदु से दूसरे बिंदु पर एक बेजियर वक्र खींचता है (यह दो TrackedObjects कनेक्ट करेगा)। इसके लिए मुझे निर्देशांक के बीच अंतर की आवश्यकता है। यदि मैं सही एंकर हूं तो उनके बीच की दूरी की गणना करने का कोई तरीका नहीं प्रदान करता है।

उत्तर

5

यह एक कठिन बिंदु है, लेकिन यहां हैक मैं अपनी परियोजनाओं में से एक में उपयोग किया जाता है: हरे रंग की रेक्ट की तुलना में एक और माता-पिता में नीली आय बनाने के लिए, इसके साथ गठबंधन रहने के लिए, जब हरे रंग की चट्टान चलता है लेकिन जब भी पीला रेक्ट (हरा रेक्ट माता पिता) से चलता है:

import QtQuick 2.0; 

Rectangle { 
    id: window; 
    width: 800; 
    height: 480; 

    property bool globalBit : true; 

    function updatePos (item_orig, item_dest, bit) { 
     var pos_abs = window.mapFromItem (item_orig.parent, item_orig.x, item_orig.y); 
     return window.mapToItem (item_dest.parent, pos_abs.x, pos_abs.y); 
    } 

    Rectangle { 
     id: rectYellow; 
     width: 400; 
     height: 300; 
     x: 300; 
     y: 200; 
     color: "yellow"; 

     onXChanged: { globalBit = !globalBit; } 
     onYChanged: { globalBit = !globalBit; } 

     MouseArea { 
      drag { 
       target: rectYellow; 
       minimumX: 0; 
       minimumY: 0; 
       maximumX: (rectYellow.parent.width - rectYellow.width); 
       maximumY: (rectYellow.parent.height - rectYellow.height); 
      } 
      anchors.fill: parent; 
     } 
     Rectangle { 
      id: rectGreen; 
      x: 100; 
      y: 100; 
      width: 50; 
      height: 50; 
      color: "green"; 

      MouseArea { 
       drag { 
        target: rectGreen; 
        minimumX: 0; 
        minimumY: 0; 
        maximumX: (rectGreen.parent.width - rectGreen.width); 
        maximumY: (rectGreen.parent.height - rectGreen.height); 
       } 
       anchors.fill: parent; 
      } 
     } 
    } 
    Rectangle { 
     id: rectBlue; 
     x: pos.x + 50; 
     y: pos.y + 50; 
     width: 50; 
     height: 50; 
     color: "blue"; 

     property var pos : updatePos (rectGreen, rectBlue, globalBit); 
    } 
} 

चाल सब वापस पहले आम पूर्वज के लिए निर्देशांक, दोनों mapfromItem और mapToItem का उपयोग कर लाने के लिए, और फिर से मूल्यांकन किया जाना समारोह के लिए मजबूर करने के लिए है, बस एक डाल ग्लोबल बुलियन ध्वज जिसे आप कंप्यूटिंग फ़ंक्शन में पास करते हैं, और यह कि आप हर बार अपने मानचित्र चाल पर चलने योग्य तत्व को उलटा करते हैं ... आपको इसे हर जगह रखना नहीं है, केवल उन वस्तुओं के माता-पिता पर जो स्थानांतरित हो सकते हैं और अंदर हैं पूर्वजों की वस्तु

तो यह काम करता है, आपकी स्थिति हमेशा सही होगी, और यह काफी स्केलेबल है और इसमें अधिक कोड नहीं है।

+0

धन्यवाद एक बहुत। सोचा नहीं होगा कि फिर से मूल्यांकन करने के लिए उस वैश्विक ध्वज का उपयोग करने का विचार किया गया है। यह गंदे लगता है लेकिन यह चाल है। –

1

मैं नहीं जानता कि क्या यह मदद मिलेगी, लेकिन ऊपर पीले रेक्ट, नीले और हरे रंग की रेक्ट रेक्ट समस्या TheBootroo ने उल्लेख के लिए, मैं इस समस्या

import QtQuick 2.0; 

Rectangle { 
id: window; 
width: 800; 
height: 480; 


Rectangle { 
    id: rectYellow; 
    width: 400; 
    height: 300; 
    x: 300; 
    y: 200; 
    color: "yellow"; 

    MouseArea { 
     drag { 
      target: rectYellow; 
      minimumX: 0; 
      minimumY: 0; 
      maximumX: (rectYellow.parent.width - rectYellow.width); 
      maximumY: (rectYellow.parent.height - rectYellow.height); 
     } 
     anchors.fill: parent; 
    } 
    Rectangle { 
     id: rectGreen; 
     x: 100; 
     y: 100; 
     width: 50; 
     height: 50; 
     color: "green"; 

     MouseArea { 
      drag { 
       target: rectGreen; 
       minimumX: 0; 
       minimumY: 0; 
       maximumX: (rectGreen.parent.width - rectGreen.width); 
       maximumY: (rectGreen.parent.height - rectGreen.height); 
      } 
      anchors.fill: parent; 
     } 
    } 
} 
Rectangle { 
    id: rectBlue; 
    //Need to acheive the below behvior(commented) 
    //x: window.x+rectYellow.x+rectGreen.x+50 
    //y: window.y + rectYellow.y +rectGreen.y+50 
    width: 50; 
    height: 50; 
    color: "blue"; 

} 
Component.onCompleted: { 
    rectBlue.x =Qt.binding(
       function() 
       { 
        //Returns window.x+rectYellow.x+rectGreen.x+rectGreen.width 
        var docRoot = null; 
        var x=rectGreen.x; 
        if(!docRoot) 
        { 
         docRoot = rectGreen.parent; 
         x+=docRoot.x; 

         while(docRoot.parent) 
         { 
          docRoot = docRoot.parent; 
          x+=docRoot.x 
         } 
        } 
        return x+rectGreen.width; 
       } 

       ) 
    rectBlue.y = Qt.binding(
       function() 
       { 
        //Returns window.y+rectYellow.y+rectGreen.y+rectGreen.height 
        var docRoot = null; 
        var y=rectGreen.y 
        if(!docRoot) 
        { 
         docRoot = rectGreen.parent; 
         y+=docRoot.y; 

         while(docRoot.parent) 
         { 
          docRoot = docRoot.parent; 
          y+=docRoot.y 
         } 
        } 
        return y+rectGreen.height; 
       } 

       ) 
    } 


} 

विचार है हल करने के लिए नीचे दिए गए कोड का इस्तेमाल किया हरे आयत के सापेक्ष नीले आयताकार की स्थिति की गणना करने के लिए, द्वारा हरे आयताकार और उसके दृश्य पूर्वजों की स्थिति की गणना करना।

इस समाधान के पीछे प्रेरणा है ->http://developer.nokia.com/Community/Wiki/How_to_create_a_Context_Menu_with_QML

+0

ऊपर उल्लिखित रंगीन रेक्ट समाधान के समान, आप ट्रैक किए गए ऑब्जेक्ट के एक्स और वाई निर्देशांक को जावास्क्रिप्ट कार्यों में बाध्य कर सकते हैं जो दृश्य पेड़ को पार करते हैं और पूर्वजों के निर्देशांक वापस करते हैं। – Programmer

0

मैं अपनी ही ItemPositionTracker.qml फ़ाइल में कोड को ले जाकर एक सा @ Shubhanga के जवाब पर सुधार करने के लिए प्रयास किया है:

import QtQuick 2.3 

Item { 
    id: root 

    property Item trackedItem 
    property Item movedItem 

    Component.onCompleted: { 
     movedItem.x = 
       Qt.binding(
        function() 
        { 
         if (trackedItem === null) return 0; 

         var docRoot = trackedItem; 
         var x = trackedItem.x; 

         while(docRoot.parent) 
         { 
          docRoot = docRoot.parent; 
          x += docRoot.x 
         } 

         return x; 
        } 

        ) 
     movedItem.y = 
       Qt.binding(
        function() 
        { 
         if (trackedItem === null) return 0; 

         var docRoot = trackedItem; 
         var y = trackedItem.y 

         while(docRoot.parent) 
         { 
          docRoot = docRoot.parent; 
          y += docRoot.y 
         } 

         return y; 
        } 

        ) 
    } 
} 

कोड कर सकते हैं अब इस तरह किसी भी QML वस्तु में जोड़ दिया:

ItemPositionTracker { 
    trackedItem: rectGreen 
    movedItem: rectBlue 
} 

rectBlue पालन rectGreen बनाता है।

2

समाधान नीचे qmlElementToTrack.onPropertyNameXChanged को गति प्रदान() और qmlElementToTrack.onPropertyNameYChanged() घटनाओं हर बार अपने माता-पिता 'एक्स' या में से एक 'y' मान बदल जाएगा।

यह प्रत्येक माता पिता की onXChanged() और onYChanged() संकेतों के लिए संलग्न करके करता है। जब उन मानों में से कोई एक बदलता है, तो यह प्रॉपर्टीनामैक्स या propertyNameY मानों को qmlElementToTrack के माता-पिता को ट्रैवर्स करके मानता है।

इसे 'रिश्तेदार' स्थानांतरित करने के लिए ('पूर्ण' के बजाय), वर्तमान जोड़ें! == qmlElementToStopAt प्रत्येक() स्थिति में।

ElementToTrack { 
 
    id: qmlElementToTrack 
 
    property real propertyNameX: 0 
 
    property real propertyNameY: 0 
 
}

setPositionChangedToParents(qmlElementToTrack); 
 

 

 
/** 
 
    Connect to each parent's 'onXChanged' and 'onYChanged' signals. 
 
*/ 
 
setPositionChangedToParents = function(current) { 
 
    while (current && current.parent) { 
 
     current.onXChanged.connect(calculatePropertyNameX); 
 
     current.onYChanged.connect(calculatePropertyNameY); 
 
     current = current.parent; 
 
    } 
 
}; 
 

 

 
/** 
 
    Disconnects the signals set to all parents. 
 
*/ 
 
removePositionChangedFromParents = function(current) { 
 
    while (current && current.parent) { 
 
     current.onXChanged.disconnect(calculatePropertyNameX); 
 
     current.onYChanged.disconnect(calculatePropertyNameY); 
 
     current = current.parent; 
 
    } 
 
}; 
 

 

 
/** 
 
    When any parent's 'x' changes, recalculate the 'x' value for the 'property name'. 
 
*/ 
 
calculatePropertyNameX = function() { 
 
    var calculatedX, current; 
 

 
    calculatedX = 0; 
 
    current = qmlElementToTrack; 
 

 
    while (current && current.parent) { 
 
     calculatedX += current.x; 
 
     current = current.parent; 
 
    } 
 

 
    propertyNameX = calculatedX; 
 
}; 
 

 

 
/** 
 
    When any parent's 'y' changes, recalculate the 'y' value for the 'property name'. 
 
*/ 
 
calculatePropertyNameY = function() { 
 
    var calculatedY, current; 
 

 
    calculatedY = 0; 
 
    current = qmlElementToTrack; 
 

 
    while (current && current.parent) { 
 
     calculatedY += current.y; 
 
     current = current.parent; 
 
    } 
 

 
    propertyNameY = calculatedY; 
 
};

+0

बहुत अच्छा। एक नोट: 'ऑनएक्स चेंज' और 'ऑन वाई चेंज' से कनेक्ट करने के अलावा, इसे शायद 'ऑनेंटेंट चेंज' से भी कनेक्ट करना चाहिए ताकि किसी भी पुन: पेरेंटिंग ट्रिकरी को भी ट्रैक किया जा सके। – Russ

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