Item :: contains始终返回true

时间:2014-09-20 10:36:58

标签: qt qml

无论输入如何,

Item::contains似乎总是返回true:

import QtQuick 2.3

Rectangle {
    width: 400
    height: 400
    color: "green"

    Rectangle {
        id: block
        width: 50
        height: 50
        color: "red"

        anchors.centerIn: parent
    }

    MouseArea {
        anchors.fill: parent

        onClicked: {
            var pnt = mapToItem( block, mouse.x, mouse.y );
            console.log( "pnt x:", pnt.x, "y:", pnt.y );
            if ( block.contains( pnt ) ) {
                console.log( "Inside" );
            } else {
                console.log( "Outside" );
            }
        }
    }
}

运行它并随机点击会得到如下输出:

qml: pnt x: 104 y: 102
qml: Inside
qml: pnt x: -113 y: -101
qml: Inside
qml: pnt x: -105 y: 111
qml: Inside
qml: pnt x: 120 y: -62
qml: Inside

正如您所见,即使输入位于内部块之外,也会打印Inside。有什么我不理解Item::contains吗?

修改

如果我将一个基本的矩形contains方法放在一起:

function myContains( pnt ) {
    return pnt.x >= 0 && pnt.x < block.width &&
           pnt.y >= 0 && pnt.y < block.height;
}

它工作正常,因此block位置和大小没有任何问题。默认的QQuickItem::contains(..)方法应该只使用基本的局部坐标矩形测试,如上所述。

EDIT2

正如@Mitch所指出的那样,object返回的Item::mapToItem(..)似乎没有转换为C ++端的QPointF。解决方案是在调用Qt.point之前将转换后的坐标推送到Item::contains

...
if ( block.contains( Qt.point( pnt.x, pnt.y ) ) ) {
...

1 个答案:

答案 0 :(得分:1)

它看起来像一个bug。如果您向QQuickItem::contains()添加调试语句,则可以看到该点未正确转换为{0, 0}

--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -6922,6 +6922,7 @@ void QQuickItem::setKeepTouchGrab(bool keep)
 bool QQuickItem::contains(const QPointF &point) const
 {
     Q_D(const QQuickItem);
+    qDebug() << Q_FUNC_INFO << point;
     return QRectF(0, 0, d->width, d->height).contains(point);
 }

输出:

qml: pnt x: 79 y: 74
bool __thiscall QQuickItem::contains(const class QPointF &) const QPointF(0,0)
qml: Inside

不幸的是(并且非常令人惊讶地)测试不会解释这一点,因为他们only test是一个自定义contains函数,并且在C ++中这样做。