Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to track the global position of an Item?
Forum Updated to NodeBB v4.3 + New Features

How to track the global position of an Item?

Scheduled Pinned Locked Moved QML and Qt Quick
12 Posts 5 Posters 22.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    njeisecke
    wrote on last edited by
    #1

    Hi!

    I would like to track the global position of an item (relative to the root item). Property binding to the item's x and y coordinates does not help because they are relative to its parent, so mapToItem would not be reevaluated if the parent is moved.

    Maybe there's something in Qml that I've missed, so before I start working on a C++ extension that provides the information (should be possible, I guess), I'm asking here.

    Thanks!

    Nils

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mbrasser
      wrote on last edited by
      #2

      Hi Nils,

      I don't think you are missing anything: the built-in QML elements don't provide any simple ways of dealing with global position changes.

      Regards,
      Michael

      1 Reply Last reply
      0
      • N Offline
        N Offline
        njeisecke
        wrote on last edited by
        #3

        ok, thanks. I'll look into doing this from the C++ side.

        1 Reply Last reply
        0
        • D Offline
          D Offline
          diro
          wrote on last edited by
          #4

          Hi Njeisecke,
          I think you really miss something, I use mapFromItem()/mapToItem() function to get the item's position in global scene.

          http://doc.qt.nokia.com/4.7-snapshot/qml-item.html#mapFromItem-method

          The document says:
          Maps the point (x, y), which is in item's coordinate system, to this item's coordinate system, and returns an object with x and y properties matching the mapped cooordinate.
          If item is a null value, this maps the point from the coordinate system of the root QML view.

          1 Reply Last reply
          0
          • N Offline
            N Offline
            njeisecke
            wrote on last edited by
            #5

            Hi diro,

            the problem is that x and y do not change if for example the item's parent is being moved. So in this case mapFromItem would not be reevaluated event though the global position changes.

            Nils

            1 Reply Last reply
            0
            • D Offline
              D Offline
              diro
              wrote on last edited by
              #6

              Hi Nils,
              I think the event issue could be solved in QML, the main idea is that if the itme's coordinate won't change but its parent will, how about leverage its notify?

              The original code may be:
              subpanel.mapToItem(null, 0, 0).x
              than, becomes:
              subpanel.mapToItem(null, (basepanel.width * 0) + 0, 0).x

              PS.The basepanel.width may changed to other properties, such as x, y, height... and so on, depends on your case

              The following is my full sample code, you may try it.

              @import QtQuick 1.1

              Rectangle {
              id: basepanel
              anchors.leftMargin: 10;
              anchors.rightMargin: 10;
              width:800;
              height: 480;
              color:"#333333";

              Rectangle {
                  id: subpanel
                  width: 657
                  height: 294
                  anchors.horizontalCenter: parent.horizontalCenter
                  anchors.verticalCenter: parent.verticalCenter
                  color:"black"
                  border.color: "#777777"
              }
              
              Text {
                  id: status
                  x: parent.width/2
                  y: parent.height/2
                  color: "#ffffff"
                  text: qsTr("Global Position of item subpanel:") +
                        subpanel.mapToItem(null, (basepanel.width * 0) + 0, 0).x +
                        "," +
                        subpanel.mapToItem(null, (basepanel.width * 0) + 0, 0).y;
                  visible: true
                  styleColor: "#a23e3e"
              }
              

              }
              @

              Besides, if you really want to monitor many properties of basepanel, you may use
              @ (basepanel.width * basepanel.height * basepanel.x * basepanel.y * 0)@

              1 Reply Last reply
              0
              • N Offline
                N Offline
                njeisecke
                wrote on last edited by
                #7

                Hi Diro,

                thank you very much for posting your example code.

                The problem is that "subpanel" is supposed to be a component. It doesn't know if the moving item is it's parent, parent parent oder parent parent parent, ...

                So to get it right you would have to iterate through the parent chain and bind to each x and y property. You also have to take possible reparenting into account.

                I guess you could do this in pure Qml. However I doubt that the amount of necessary bindings and function calls would give reasonable performance in more complex applications.

                So as soon as time admits, I'm going to check what could be done from the C++ side. The downside of this approach might be that I'll have to do it again for the scene graph.

                Nils

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  diro
                  wrote on last edited by
                  #8

                  Hi Nils,
                  Okay, I understand your problem now. And I also interested in your C++ solution, hope you can share with us in the future, thanks :-)

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    Merinas
                    wrote on last edited by
                    #9

                    Hi,

                    Did you get any progress on that ?

                    Merinas

                    1 Reply Last reply
                    0
                    • N Offline
                      N Offline
                      njeisecke
                      wrote on last edited by
                      #10

                      No, not really.

                      I've been talking about this with some Qt developers at DevDays and they came to the conclusion that this would be pretty difficult to implement generally without sacrificing overall system performance.

                      You should be able to connect to all xChanged and yChanged signals of the item's parent chain but I have not tried this yet. Seems to be the only possibility though.

                      Nils

                      1 Reply Last reply
                      0
                      • F Offline
                        F Offline
                        feldifux
                        wrote on last edited by
                        #11

                        Yes, connecting an item's own x/y-Changed signals to the xChanged and yChanged signals of all parents is possible - I tried it and it works fine. But I do not recommend it for items that change often, because the performance penalty is significant! If you have control over the items you want to track, it would be the best solution to write a custom QDeclarativeItem in C++ and overwrite the itemChange function from QGraphicsItem: "QGraphicsItem itemChange function":http://doc.qt.nokia.com/4.7-snapshot/qgraphicsitem.html#itemChange.

                        Regarding the doc, this also has a performance impact, but presumably not that much compared to the parent-signal-connection approach.

                        Chris

                        Founder of Felgo SDK - http://felgo.com/qt

                        Felgo simplifies

                        • Mobile App Dev with Qt esp. iOS & Android
                        • Game Development with Qt

                        What others say

                        Felgo scored #1 in Cross-Platform App Development Tools Report - see why: https://goo.gl/rgp3rq

                        1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          Merinas
                          wrote on last edited by
                          #12

                          Maybe we need a specific Item to provide this functionnality or add a new property in item to add tracking global pos.

                          For now I used the flag ItemSendsScenePositionChanges in a new item. My purpose is to anchor a punctual item to another punctual item anywhere ni the QML tree here what I used :

                          @class AnchorPoint : public QDeclarativeItem
                          {
                          Q_OBJECT
                          Q_DISABLE_COPY(AnchorPoint)
                          Q_PROPERTY(AnchorPoint* anchorTo READ anchorTo WRITE setAnchorTo NOTIFY anchorToChanged)

                          public:
                          AnchorPoint(QDeclarativeItem *parent = 0)
                          : QDeclarativeItem(parent)
                          , m_anchorTo(NULL)
                          {
                          setFlag(ItemSendsScenePositionChanges, true);
                          }
                          ~AnchorPoint(){}

                          AnchorPoint* anchorTo() const { return m_anchorTo;}
                          void setAnchorTo(AnchorPoint* anchorPoint)
                          {
                              if(anchorPoint != m_anchorTo)
                              {
                                  if(m_anchorTo != NULL)
                                  {
                                        disconnect(m_anchorTo,SIGNAL(scenePosChanged()),this,SLOT(anchorPosChanged()));
                                  }
                                  m_anchorTo = anchorPoint;
                                  if(m_anchorTo != NULL)
                                 {
                                      connect(m_anchorTo,SIGNAL(scenePosChanged()),this,SLOT(anchorPosChanged()));
                                 }
                              }
                          }
                          
                          QVariant itemChange(GraphicsItemChange change, const QVariant &value)
                          {
                              if (change == ItemScenePositionHasChanged && scene())
                              {
                                  emit scenePosChanged();
                              }
                              return QGraphicsItem::itemChange(change, value);
                          }
                          

                          signals:
                          void anchorToChanged();
                          void scenePosChanged();

                          protected slots:
                          void anchorPosChanged()
                          {
                          QGraphicsItem* anchorParent = (QGraphicsItem*)m_anchorTo->parentItem();
                          if(anchorParent==NULL)
                          {
                          qDebug() << "Item anchored to has no parent : can't anchored to it";
                          return;
                          }

                              if(parentItem()==NULL)
                              {
                                  qDebug() << " Item has no parent : can't be anchored ";
                                  return;
                              }
                          
                              QPointF anchorPos = m_anchorTo->pos();
                              setPos(anchorParent->mapToItem((const QGraphicsItem*)parentItem(),anchorPos));
                          }
                          

                          private:
                          AnchorPoint* m_anchorTo;
                          };@

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved