【问题标题】:Why Qt QML doesn't properly bind properties?为什么 Qt QML 不能正确绑定属性?
【发布时间】:2015-05-06 20:46:37
【问题描述】:

这很奇怪,因为我在另一个 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 会发生变化,但Item 可见性始终保持不变!我的物品还有许多其他属性(例如height: isExpanded ? someval : 0),它们也没有改变!如果我总是手动更改所有内容,它有点工作,但那有什么意义呢?在另一个 QML 中,我使用了类似的模式,并且它可以工作!

但是!如果我输入,例如onDoubleClicked/另一个按钮按下: myId.visible = Qt.binding(function() {return isExpanded}) 它可以正常工作!因此,由于某些未知原因,它不会在应该在常规属性声明中“绑定”它们 (visible: isExpanded)。

所以问题是,我真的需要明确告诉 Qt 绑定属性以使其工作吗?

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

【问题讨论】:

  • “其他东西”或其他任何东西是否分配给 myId.visible 并破坏绑定?这是我唯一能想到的。或者 MyCustomItem 声明了自己的可见属性,而 impl 包含错误。
  • 不,它没有。如果某些东西会破坏绑定,它是否也会破坏“硬编码”绑定myId.visible = Qt.binding(function() {return isExpanded})? MyCustomItem 只是一个 Item {},其中包含其他内容。它本身内部根本不使用可见属性。我“可能”唯一要重新分配的是项目 ID(它在 qml 文件中有自己的内部 ID,但因为在我有问题的 qml 中有两个 - 他们分配了不同的 ID)
  • 我不喜欢你的态度。您需要习惯于您没有世界上所有的知识,如果有经验的人说您只是打破束缚,那确实意味着您做到了。这可能是世界上最违反直觉的错误,但是,嘿,是谁设计的?或许您并不完全理解所使用的机制或语言的目的。

标签: qt qml qt5 qtquick2


【解决方案1】:

所以问题是,我真的需要明确告诉 Qt 绑定属性以使其工作吗?

是的。

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

虽然您的实际问题是由于成为 QML 范围规则的受害者。你的MyCustomItem 类型有一个isExpanded 属性,所以当你声明时:

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

您实际上将visible 绑定到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
    }
}

【讨论】:

  • 这不是我问题的答案!看看我的代码,请再读一遍!问题是由于某种原因绑定语法 DOESN'T WORK (虽然是必要的,但使用 Qt.binding() 确实有效)。我不知道为什么。
  • @DanM。 “看看我的代码,请再读一遍!”您的代码完美运行。绑定不会失败(没有错误消息),这意味着您正在破坏绑定,只是不在您提供的代码中。
  • @cmannett85 我将 MyCustomItem 代码简化为:pastebin.com/1RX015Sk 那里绝对没有“可见性”更改 - 它仍然不起作用。它与我的其他自定义 qmls 一起使用,它在命令式 qt.bind 之后工作,但它不能开箱即用。如果有任何重新分配 - 它们是隐藏和隐含的。
  • @DanM。我发现了这个问题。
  • @cmannett85 而且,它不仅仅是可见的。该项目的 ALL 属性会发生这种情况。如果只有可见性是问题,我可以简单地将 myItems 封装在 Item 中并更改 Item 的可见属性(有效)。但我也想绑定 height,y 等。
【解决方案2】:

我发现了问题!非常不明显(在任何地方都没有找到记录)并且它默默地失败了。 问题是MyCustomItem 包含一个与外部布尔属性isExpanded 同名的属性,所以在这段代码中:

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

isExpanded 来自MyCustomItem。但没有任何迹象表明。好吧,现在我知道这可能会发生,并且如果再次发生,可能会发现它,但这确实违反直觉。如果它不是我的物品而是别人的,我不知道它有这样的属性怎么办? Qt 创建者至少可以警告可能存在的歧义。

【讨论】:

  • 它一点也不违反直觉,它遵循几乎所有语言的范围规则。这与在 C:{ int a = 0; { int a = 1; int b = a;} } 中执行此操作并期望 b 为 0 没有什么不同。
  • @cmannett85 这是违反直觉的,因为语法不同。声明项目时,您看不到项目的“内部”。更像是如果你有(实际上没有,但它的外观和使用方式)int a = 0; Item b; b.setC(a) 如果将 setC 分配给 c 某个内部(到 b)属性 a 而不是我们所知道的我们,那将是违反直觉的。
  • 语法不同,作用域语义不同(至少从这个 pov 来看)。 Qt Creator 无法对可行的事情发出警告,即使在大多数情况下可能会让人头疼。
猜你喜欢
  • 1970-01-01
  • 2018-07-24
  • 2013-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-13
  • 2011-06-20
  • 1970-01-01
相关资源
最近更新 更多