为什么Qt-QML不能正确绑定属性?

为什么Qt-QML不能正确绑定属性?,qt,qml,qt5,qtquick2,Qt,Qml,Qt5,Qtquick2,这很奇怪,因为我在另一个QML文件中使用了几乎相同的模式,而且工作正常!我确信我不会在任何地方重新分配值——我所知道的唯一可以使属性保持静态的东西! 我有一个类似的例子,这是一个简化的例子,可能会像预期的那样工作: Item { property bool isExpanded: false MouseArea { anchors.fill: parent onClicked: { isExpanded = !isExpan

这很奇怪,因为我在另一个QML文件中使用了几乎相同的模式,而且工作正常!我确信我不会在任何地方重新分配值——我所知道的唯一可以使属性保持静态的东西! 我有一个类似的例子,这是一个简化的例子,可能会像预期的那样工作:

Item {
    property bool isExpanded: false
    MouseArea {
        anchors.fill: parent
        onClicked: {
            isExpanded = !isExpanded
            console.log(isExpanded)
            console.log(myId.visible)
        }
    }
    MyCustomItem {
        id: myId
        visible: isExpanded
        // other stuff
    }
}
我单击后扩展了更改,但项目可见性始终保持不变!我的物品还有很多其他属性,比如高度:isExpanded?someval:0,它也不会改变!如果我总是手动更改所有内容,它会起作用,但那又有什么意义呢?在另一个QML中,我使用了一个类似的模式,它在那里工作

但是!例如,如果我按下双按钮/另一个按钮: myId.visible=Qt.bindingfunction{return isExpanded} 它的工作,因为它应该!所以,出于某种未知的原因,它不会在常规属性声明visible:isExpanded中“绑定”它们

所以问题是,我真的需要显式地告诉Qt绑定属性以使其工作吗

编辑:明确说明:我确信我不会在任何地方重新分配可见属性。我查过了。虽然qml的大小只有大约100行,但我使用ctrl+f查找任何可见的内容,除了已经提到的内容外,没有发现其他内容。 如果有更可靠的方法来判断来自/检查可能在某处或某处重新分配的内容,请告诉我

所以问题是,我真的需要显式地告诉Qt绑定属性以使其工作吗

声明属性时,可以使用绑定语法,例如visible:isExpanded。但是使用普通JavaScript语法在命令式代码中设置属性,即赋值运算符将破坏任何现有绑定并覆盖属性值。如果要在命令式代码中显式设置属性绑定,请使用Qt.binding方法

虽然您的实际问题是由于成为QML范围规则的受害者。MyCustomItem类型具有isExpanded属性,因此在声明时:

MyCustomItem {
    id: myId
    visible: isExpanded
    // other stuff
}
实际上,您的绑定对MyCustomItem::isExpanded可见。因此,要解决这个问题,请明确指出您所指的isExpanded:

Item {
    id: base
    property bool isExpanded: false
    MouseArea {
        anchors.fill: parent
        onClicked: {
            isExpanded = !isExpanded
            console.log(isExpanded)
            console.log(myId.visible)
        }
    }
    MyCustomItem {
        id: myId
        visible: base.isExpanded
        // other stuff
    }
}
所以问题是,我真的需要显式地告诉Qt绑定属性以使其工作吗

声明属性时,可以使用绑定语法,例如visible:isExpanded。但是使用普通JavaScript语法在命令式代码中设置属性,即赋值运算符将破坏任何现有绑定并覆盖属性值。如果要在命令式代码中显式设置属性绑定,请使用Qt.binding方法

虽然您的实际问题是由于成为QML范围规则的受害者。MyCustomItem类型具有isExpanded属性,因此在声明时:

MyCustomItem {
    id: myId
    visible: isExpanded
    // other stuff
}
实际上,您的绑定对MyCustomItem::isExpanded可见。因此,要解决这个问题,请明确指出您所指的isExpanded:

Item {
    id: base
    property bool isExpanded: false
    MouseArea {
        anchors.fill: parent
        onClicked: {
            isExpanded = !isExpanded
            console.log(isExpanded)
            console.log(myId.visible)
        }
    }
    MyCustomItem {
        id: myId
        visible: base.isExpanded
        // other stuff
    }
}

我发现了问题!非常不明显,在任何地方都找不到文档,它会默默地失败。 问题在于MyCustomItem包含一个与outer booleal属性同名的属性,因此在此代码中:

MyCustomItem {
    id: myId
   visible: isExpanded
 // other stuff
}

isExpanded来自MyCustomItem。但没有任何迹象表明这一点。好吧,现在我知道这可能会发生,如果它再次发生,我可能会发现它,但这确实是违反直觉的。如果它不是我的东西,而是别人的,而我不知道它有这样的属性呢?Qt creator至少可以警告可能存在的歧义。

我发现了问题!非常不明显,在任何地方都找不到文档,它会默默地失败。 问题在于MyCustomItem包含一个与outer booleal属性同名的属性,因此在此代码中:

MyCustomItem {
    id: myId
   visible: isExpanded
 // other stuff
}

isExpanded来自MyCustomItem。但没有任何迹象表明这一点。好吧,现在我知道这可能会发生,如果它再次发生,我可能会发现它,但这确实是违反直觉的。如果它不是我的东西,而是别人的,而我不知道它有这样的属性呢?Qt creator至少可以警告可能存在的歧义。

是否有其他内容或任何其他内容分配给myId.visible并破坏绑定?那是我唯一能想到的。或者MyCustomItem声明了自己的visible属性,而impl包含错误。不,它没有。如果有什么东西会破坏绑定,那么它不也会破坏硬编码绑定吗?myId.visible=Qt.bindingfunction{return isExpanded}?MyCustomItem只是一个{}项,其中包含其他内容。它本身根本不使用visible属性。我可能会重新分配的唯一一件事是项目id,它在qml文件中有自己的内部id,但因为在我有问题的qml中有两个,它们有不同的id分配给它们,我不喜欢你的态度。你需要习惯于你并不拥有世界上所有的知识,如果有经验的人说你只是打破了束缚,那就意味着你做到了。这可能是世界上最违反直觉的错误

世界但是嘿,是谁设计的?也许您不完全理解所使用的机制或语言的用途。是否有其他内容或任何其他内容分配给myId.visible并破坏绑定?那是我唯一能想到的。或者MyCustomItem声明了自己的visible属性,而impl包含错误。不,它没有。如果有什么东西会破坏绑定,那么它不也会破坏硬编码绑定吗?myId.visible=Qt.bindingfunction{return isExpanded}?MyCustomItem只是一个{}项,其中包含其他内容。它本身根本不使用visible属性。我可能会重新分配的唯一一件事是项目id,它在qml文件中有自己的内部id,但因为在我有问题的qml中有两个,它们有不同的id分配给它们,我不喜欢你的态度。你需要习惯于你并不拥有世界上所有的知识,如果有经验的人说你只是打破了束缚,那就意味着你做到了。这可能是世界上最违反直觉的错误,但嘿,是谁设计的?也许你没有完全理解你所使用的力学或语言的目的。这不是我问题的答案!看看我的代码,请再读一遍!问题是绑定语法由于某些原因不起作用,尽管是命令式的,但使用Qt.binding确实起作用。“我不明白为什么。”丹姆说。看看我的代码,请再读一遍!你的代码工作得很好。绑定不会在没有错误消息的情况下失败,这意味着您正在破坏绑定,而不是在您提供的代码中。@cmannett85我将MyCustomItem代码简化为:那里肯定没有可见性更改,而且仍然不起作用。它与我的其他自定义QML一起工作,在命令qt.bind之后工作,但它不能开箱即用。如果有任何重新分配-它们是隐藏的和隐式的。@DanM。我已经发现了这个问题。@cmannett85而且,它不仅仅是可见的。它发生在该项的所有属性上。如果只是可见性的问题,我可以简单地将myItems封装在Item中,并更改Item的visible属性。但我也想约束身高,y和其他人。这不是我问题的答案!看看我的代码,请再读一遍!问题是绑定语法由于某些原因不起作用,尽管是命令式的,但使用Qt.binding确实起作用。“我不明白为什么。”丹姆说。看看我的代码,请再读一遍!你的代码工作得很好。绑定不会在没有错误消息的情况下失败,这意味着您正在破坏绑定,而不是在您提供的代码中。@cmannett85我将MyCustomItem代码简化为:那里肯定没有可见性更改,而且仍然不起作用。它与我的其他自定义QML一起工作,在命令qt.bind之后工作,但它不能开箱即用。如果有任何重新分配-它们是隐藏的和隐式的。@DanM。我已经发现了这个问题。@cmannett85而且,它不仅仅是可见的。它发生在该项的所有属性上。如果只是可见性的问题,我可以简单地将myItems封装在Item中,并更改Item的visible属性。但我还想绑定height、y和其他语言。它一点也不违反直觉,它遵循的范围规则与几乎所有语言都一样。在C中执行此操作没有什么不同:{int a=0;{int a=1;int b=a;}}并期望b为0。@cmannett85这是违反直觉的,因为语法不同。当你申报物品时,你看不到它的内部。这更像是如果你在现实中没有,但它的外观和使用int a=0;项目b;b、 setCa如果setC给c分配了一些b属性a的内部属性,而不是我们所知道的我们的属性,这将是违反直觉的。语法是不同的,范围语义至少不是从这个角度来看的。Qt Creator无法对可行的东西发出警告,即使它在大多数情况下可能会让人头痛。它一点也不违反直觉,它遵循与几乎所有语言相同的范围规则。在C中执行此操作没有什么不同:{int a=0;{int a=1;int b=a;}}并期望b为0。@cmannett85这是违反直觉的,因为语法不同。当你申报物品时,你看不到它的内部。这更像是如果你在现实中没有,但它的外观和使用int a=0;项目b;b、 setCa如果setC给c分配了一些b属性a的内部属性,而不是我们所知道的我们的属性,这将是违反直觉的。语法是不同的,范围语义至少不是从这个角度来看的。Qt Creator无法为可行的事情发出警告,即使在大多数情况下,这可能是一件令人头痛的事情。