Qt 如何省去“;检测到属性“的绑定循环”;警告

Qt 如何省去“;检测到属性“的绑定循环”;警告,qt,qml,qtquick2,qt5.5,Qt,Qml,Qtquick2,Qt5.5,我决定重写这个问题。我试着把它说得简短明了,但没有成功 我试图实现的是一个对象,我可以放在任何东西上(矩形,图像等等),让它对触摸手势做出反应。不幸的是,我遇到了一个我无法解决的问题。我找不到帮助,所以我在这里试试 下面是简单的main.qml: import QtQuick 2.5 import QtQuick.Controls 1.3 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 ApplicationWindow { t

我决定重写这个问题。我试着把它说得简短明了,但没有成功

我试图实现的是一个对象,我可以放在任何东西上(
矩形
图像
等等),让它对触摸手势做出反应。不幸的是,我遇到了一个我无法解决的问题。我找不到帮助,所以我在这里试试

下面是简单的
main.qml

import QtQuick 2.5
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2

ApplicationWindow {
    title: qsTr("Touch surface test")
    width: 640
    height: 480
    visible: true


    Rectangle {
        width: 200
        height: 60
        color: "blue"

        MyTouchSurface {
            id: myTouchSurface
            anchors.fill: parent
        }
    }

}
这是MyTouchSurface.qml

import QtQuick 2.5

MultiPointTouchArea {
    id: myTouchSurface

    // this is object I want to respond to touch gestures
    property Item target: parent

    // this is object I want to keep target in. I won't let target get out of it
    property Item container: parent.parent

    property double targetX: target.x
    property double targetY: target.y
    property double centerX: target.width / 2
    property double centerY: target.height / 2
    property double lastTouchX
    property double lastTouchY
    property double lastXDrag
    property double lastYDrag

    // here I calculate received touches and move target
    onPressed: {
        lastTouchX = touchPoints[0].sceneX
        lastTouchY = touchPoints[0].sceneY
        if (slidingAnimation.running)
            slidingAnimation.stop()
    }
    onTouchUpdated: {
        if (touchPoints.length) {
            target.x += touchPoints[0].sceneX - lastTouchX
            target.y += touchPoints[0].sceneY - lastTouchY
            lastXDrag = touchPoints[0].sceneX - lastTouchX
            lastYDrag = touchPoints[0].sceneY - lastTouchY
            lastTouchX = touchPoints[0].sceneX
            lastTouchY = touchPoints[0].sceneY
        }
        else
            startSliding()
    }

    // when lifting fingers off screen I want to slide target across it's container
    function startSliding() {
        slidingAnimation.toX = target.x + lastXDrag * 10
        slidingAnimation.toY = target.y + lastYDrag * 10
        slidingAnimation.restart()
    }

    // This is animation responsible for sliding the target
    ParallelAnimation {
        id: slidingAnimation
        property double toX
        property double toY
        property int animationDuration: 250
        NumberAnimation {
            target: myTouchSurface.target
            property: "x"
            to: slidingAnimation.toX
            duration: slidingAnimation.animationDuration
            easing.type: Easing.OutQuad
        }
        NumberAnimation {
            target: myTouchSurface.target
            property: "y"
            to: slidingAnimation.toY
            duration: slidingAnimation.animationDuration
            easing.type: Easing.OutQuad
        }
    }

    // this is how I keep target object within container
    onTargetXChanged: {
        if (container != null) {
            if (target.x + centerX < 0)
                target.x = -centerX
            else if (target.x + centerX > container.width)
                target.x = container.width - centerX
        }
    }
    onTargetYChanged: {
        if (container != null) {
            if (target.y + centerY < 0)
                target.y = -centerY
            else if (target.y + centerY > container.height)
                target.y = container.height - centerY
        }
    }
}
导入QtQuick 2.5
多点接触区{
id:myTouchSurface
//这是我想对触摸手势做出反应的对象
属性项目标:父级
//这是我想让目标留在里面的物体。我不会让目标离开它
属性项容器:parent.parent
属性double targetX:target.x
属性double targetY:target.y
属性double centerX:target.width/2
属性双中心:target.height/2
属性double lastTouchX
财产双重所有权
属性双lastXDrag
属性双重lastYDrag
//在这里,我计算收到的接触和移动目标
按下按钮:{
lastTouchX=接触点[0]。sceneX
lastTouchY=接触点[0]。sceneY
如果(滑动动画运行)
滑动动画。停止()
}
更新日期:{
if(接触点长度){
target.x+=接触点[0]。sceneX-lastTouchX
target.y+=接触点[0]。sceneY-lastTouchY
lastXDrag=接触点[0]。sceneX-lastTouchX
lastYDrag=接触点[0]。场景-lastTouchY
lastTouchX=接触点[0]。sceneX
lastTouchY=接触点[0]。sceneY
}
其他的
开始滑动()
}
//当把手指抬离屏幕时,我想把目标滑过它的容器
函数startSliding(){
slidenganimation.toX=target.x+lastXDrag*10
slidenganimation.toY=target.y+lastYDrag*10
slidenganimation.restart()
}
//这是负责滑动目标的动画
平行动画{
id:滑动动画
属性双重toX
属性双重玩具
属性int animationDuration:250
数字化{
目标:myTouchSurface.target
属性:“x”
收件人:slidenganimation.toX
持续时间:SlidengAnimation.animationDuration
easing.type:easing.OutQuad
}
数字化{
目标:myTouchSurface.target
属性:“y”
致:SlidengAnimation.toY
持续时间:SlidengAnimation.animationDuration
easing.type:easing.OutQuad
}
}
//这就是我如何将目标对象保存在容器中的方法
onTargetXChanged:{
if(容器!=null){
如果(目标x+中心x<0)
target.x=-centerX
else if(target.x+centerX>container.width)
target.x=container.width-centerX
}
}
onTargetYChanged:{
if(容器!=null){
如果(目标y+中心y<0)
target.y=-centerY
否则如果(target.y+centerY>container.height)
target.y=container.height-centerY
}
}
}
我希望在MyTouchSurface中包含所有计算和函数,以便在其他对象上应用并在其他项目中使用它

我的问题是我不知道如何防止目标对象移出容器。嗯,这里的代码工作得很好,但它也会生成关于绑定循环的非常难看的错误

目前的情况是:

  • 当目标的x和y发生变化时,我会检查它们
  • 如果x或y超出指定区域,我将其移回
  • 我再次收到信号“x已更改”或“y已更改”
  • 我收到了关于循环的错误,因为我的函数再次执行
所以我在问:有没有其他简单的方法来防止对象飞离屏幕,同时不接收绑定循环错误

我知道我可以使用
Timer
不时检查目标的
x
y
,并将它们带回来

我知道我可以更改动画的
easing
duration
,使其在容器边界上停止,但看起来好像已停止

真的。难道没有简单的方法吗


不起作用的事情:

  • 在容器外部检测到对象后停止动画(如果它移动非常快,它将停止在屏幕外)
  • 停止动画,然后更改目标的
    x
    y


谢谢大家到目前为止对我的帮助。很高兴知道我不是这里唯一的人:)

我想你的问题是你更新了属性更新处理程序(
onTargetXChanged()
)中的
targetX
target.x
(分别是
y

这可能被QML引擎作为一个biding循环拾取,就像您从
onTargetXChanged()
更改
target.x
一样,信号
onTargetXChanged()
将在属性
double targetX:target.x
中绑定到它时再次触发

您可以尝试以下方法:

TouchArea {
  property Item target  //  target is the Image object being moved
  property double targetX: target.x
  property double targetY: target.y

  onTargetXChanged: {
    /* if object is out of specified area move x respectively */
    performPropertyUpdate(args)
  }
  onTargetYChanged: {
    /* if object is out of specified area move y respectively */
    performPropertyUpdate(args)
  }

  function performPropertyUpdate(args) {
    /* actual setting of target.x or target.y */
  }
}

要解决此问题,
myX
应该是
x
的别名

property alias myX: rectangle2.x

您遇到此问题的原因是
myX
正在更改
x
的值,
x
正在更改
myX
的值:一个循环。

解决方案是只需使用
连接即可:

import QtQuick 2.5

MultiPointTouchArea {
    id: myTouchSurface

    // this is object I want to respond to touch gestures
    property Item target: parent

    // this is object I want to keep target in. I won't let target get out of it
    property Item container: parent.parent

    property double targetX: target.x
    property double targetY: target.y
    property double centerX: target.width / 2
    property double centerY: target.height / 2
    property double lastTouchX
    property double lastTouchY
    property double lastXDrag
    property double lastYDrag

    // here I calculate received touches and move target
    onPressed: {
        lastTouchX = touchPoints[0].sceneX
        lastTouchY = touchPoints[0].sceneY
        if (slidingAnimation.running)
            slidingAnimation.stop()
    }
    onTouchUpdated: {
        if (touchPoints.length) {
            target.x += touchPoints[0].sceneX - lastTouchX
            target.y += touchPoints[0].sceneY - lastTouchY
            lastXDrag = touchPoints[0].sceneX - lastTouchX
            lastYDrag = touchPoints[0].sceneY - lastTouchY
            lastTouchX = touchPoints[0].sceneX
            lastTouchY = touchPoints[0].sceneY
        }
        else
            startSliding()
    }

    // when lifting fingers off screen I want to slide target across it's container
    function startSliding() {
        slidingAnimation.toX = target.x + lastXDrag * 10
        slidingAnimation.toY = target.y + lastYDrag * 10
        slidingAnimation.restart()
    }

    // This is animation responsible for sliding the target
    ParallelAnimation {
        id: slidingAnimation
        property double toX
        property double toY
        property int animationDuration: 250
        NumberAnimation {
            target: myTouchSurface.target
            property: "x"
            to: slidingAnimation.toX
            duration: slidingAnimation.animationDuration
            easing.type: Easing.OutQuad
        }
        NumberAnimation {
            target: myTouchSurface.target
            property: "y"
            to: slidingAnimation.toY
            duration: slidingAnimation.animationDuration
            easing.type: Easing.OutQuad
        }
    }

    Connections{
        target:myTouchSurface.target
        onXChanged:{
            if (container != null) {
                if (target.x + centerX < 0)
                    target.x = -centerX
                else if (target.x + centerX > container.width)
                    target.x = container.width - centerX
            }
        }

        onYChanged:{
            if (container != null) {
                if (target.y + centerY < 0)
                    target.y = -centerY
                else if (target.y + centerY > container.height)
                    target.y = container.height - centerY
            }
        }
    }

    // this is how I keep target object within container
//    onTargetXChanged: {

//    }
//    onTargetYChanged: {

//    }
}
导入QtQuick 2.5
多点接触区{
id:myTouchSurface
//这是我想对触摸手势做出反应的对象
属性项目标:父级
//这是我想让目标留在里面的物体。我不会让目标离开它
属性项容器:parent.parent
属性double targetX:target.x
财产加倍