Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QML mouse absolute position in MouseArea

How to get the absolute mouse position from the mouse area ? I need to have it to show a popup a the correct position

Item {
    Menu {
        id: menu
        MenuItem {
            onTriggered: {
               // Need Mouse absolute position
            }
        }
    }
    MouseArea {
        id: mouseArea
        anchors.fill: parent
        onClicked: {
            menu.popup()
        }
    }
like image 367
user14416 Avatar asked Oct 15 '13 22:10

user14416


3 Answers

Short answer

  • Map to/from another Item: mapToItem, mapFromItem
  • Map to/from global (from Qt 5.7): mapToGlobal, mapFromGlobal
    onClicked: {
        var positionInPopup = mapToItem(popup, mouse.x, mouse.y)
    }

Longer answer

Like hinted by indalive, the preferred method for mapping coordinates is by using mapToItem, available for any Item. It transforms coordinates (and size) from current Item coordinates system (if not specified otherwise) to another Item coordinates system. And the mapFromItem counterpart does the reverse, naturally.

From Qt 5.7, you also have mapToGlobal, which will give you coordinates in the system/screen referential.

MouseArea {

    // ...

    onPositionChanged: {
        var positionInRoot = mapToItem(root, mouse.x, mouse.y)
        var positionInWindow = mapToItem(window.contentItem, mouse.x, mouse.y)
        var globalPosition = mapToGlobal(mouse.x, mouse.y)

        console.log("For root: " + positionInRoot )
        console.log("For window: " + positionInWindow)
        console.log("For system: " + globalPosition)
    }
}

Given the example above, and ...

  • your MouseArea is close to root, a bit further from your Window top left corner
  • the Window itself is 1000px+ from the leftmost of your screen(s)

... you will see:

For root: QPointF(10, 0)

For window: QPointF(150, 100)

For system: QPointF(1230, 120)

Caveat with Window type

When converting to/from a Window (QML type), you need to use its contentItem property, as mapTo/From only work with Items.

like image 199
Adrien Leravat Avatar answered Nov 19 '22 12:11

Adrien Leravat


You probably found the answer already, but I'll put my solution here for others looking for the same thing.

The below function will find the absolute position of the mouse area. And then you can add mouseX and mouseY accordingly to get mouse position.

Item {
  Menu {
    id: menu
    MenuItem {
      onTriggered: {
        var absolutePos = getAbsolutePosition(source);
        // Need Mouse absolute position
      }
    }
  }
  MouseArea {
    id: mouseArea
    anchors.fill: parent
    onClicked: {
      menu.popup()
    }
  }
  function getAbsolutePosition(node) {
      var returnPos = {};
      returnPos.x = 0;
      returnPos.y = 0;
      if(node !== undefined && node !== null) {
          var parentValue = getAbsolutePosition(node.parent);
          returnPos.x = parentValue.x + node.x;
          returnPos.y = parentValue.y + node.y;
      }
      return returnPos;
  }
}
like image 6
Blastings Avatar answered Nov 19 '22 11:11

Blastings


In this case mouseArea fills his parent (anchors.fill: parent), therefore mouseArea.mouseX and mouseArea.mouseY are absolute mouse position. For relative positions you should use mapFromItem and mapToItem functions http://doc.qt.io/qt-5/qml-qtquick-item.html#mapToItem-method

like image 4
indalive Avatar answered Nov 19 '22 11:11

indalive