Question

The application below outputs coordinates mapped from one QQuickItem to another. According to the docs:

object mapToItem(Item item, real x, real y)
Maps the point (x, y) or rect (x, y, width, height), which is in this item's coordinate system, to item's coordinate system, and returns an object with x and y (and optionally width and height) properties matching the mapped coordinate.

I expect the output to be something like this:

0 0
1 1
2 2

but I get:

QPointF(9, 6)   100  
QPointF(9, 5)   100  
QPointF(8, 5)   100  

Why is the type of the mapped.x a QPointF? I expected it to be a floating-point value. What is an actual mapped type?

import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Window 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    width: 640
    height: 480

    Rectangle {
        anchors.fill: parent
        id: r0
        color: "green"
        Rectangle {
            x: 50; y:100; width: 100; height: 100;
            id: r
            color: "yellow"
            MouseArea {
                id: mousearea
                anchors.fill: parent
                hoverEnabled: true
                onPositionChanged: {
                    var mouseP = Qt.point(mouse.x, mouse.y);
                    var mapped = r.mapToItem(r0, mouseP);
                    console.log(mapped.x, ' ', mapped.y);
                }
            }
        }
    }
}

UPDATE1: QQuickItem has mapToItem with 2 args and Item has mapToItem with 3 args. Which one is called in the code above?

Was it helpful?

Solution

In your case, mapToItem expects 3 parameters. You don't need to create a point first.

onPositionChanged: {
    var mapped = r.mapToItem(r0, mouse.x, mouse.y);
    console.log(mapped.x, ' ', mapped.y);
}

Background note: This seems to be kind of a bug, which I just reported.

Your code calls QQuickItem::mapToItem() for two reasons. First, QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const; is not INVOKABLE, i.e. it is not exposed from C++ to QML. Second, QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const; returns a QPointF directly who's internal properties are called xp and yp instead of x and y (this can be observed using the debugger).

In QQuickItem::mapToItem() x and y are forced by C++ to be of type qreal, which is an alias for the C++ double. Even if (v = (*args)[1])->asDouble() freaks out completely, x must be

  • ordinary double value
  • NaN
  • +∞
  • −∞
  • -0
  • +0.

In your case it should be NaN. y = 0 because parameter 3 is not set. Thus a point (NaN, 0) is created. From that point on, the rest of the calculations don't make any sense but error handling is missing.

There is a new JavaScript engine used from Qt 5.2 on. In 5.1 and before, V8 was used, which returns a NaN instead of a QPointF to QML.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top