WRITE
方法,但除了初始的强制设置之外,它永远不会改变,因此我觉得NOTIFY
是多余的,因为在使用时它已经设置了该值,并且它永远不会改变。然而,QML并不分享我的感受,而且无论如何都会产生“表达式取决于不可通知的属性”的警告。
由于对象实例化的方式,使用属性是设置该值的唯一适用方式,不能使用可调用的setter,因为这样需要对象已经“完成”,而没有该值它无法真正完成。因此需要使用属性机制和
WRITE
方法,这不幸地导致Qt认为该属性将会改变。我尝试将属性设置为CONSTANT
,但似乎与具有WRITE
方法不兼容。我已经放置了一个虚假信号作为暂时措施来处理警告,但我更喜欢有一种更优雅的方法来处理这个问题。再次强调,该设计实际上消除了在初始设置之后设置此值的可能性,但由于它是一个C++对象并且需要按对象设置该值,因此不适用于使用QML
readonly property
。有没有一种解决这个问题的方法,而不涉及冗余信号?
只是为了澄清,这里的根本问题是,在其当前状态下,QML几乎无法初始化在C++中实现的对象的只读属性。这样的属性将没有setter(如果有,则会产生“取决于...”警告),并且没有办法将值传递给对象的构造函数。如下面的答案所述,有一些解决方法,但它们要么应用受限,要么非常不方便。在C++中,您甚至可以对每个实例进行const成员的初始化,通过将值传递给执行初始化的构造函数的初始化器列表,但在QML中不行。即使在纯QML中,只读属性也必须在现场初始化,不能将它们保留未初始化(
readonly property type name
没有: statement
)并将其延迟到实例化并获得每个实例初始化(Obj { name : initValue }
)。您可以这样做:Item { // T.qml
readonly property int r : w
property int w
}
...
T { w: value }
但这有点违背了初衷...而且考虑到一个属性只能在实例化时的其主体中"绑定"一次,我认为这可以看作是一种初始化操作,而进一步的赋值或命令式重新绑定(Qt.binding()
)则是被禁止的。没有冗余通知信号的setter可以解决问题,然而qtquick的实现设计假定如果它有一个setter,它将会被改变,因此会抱怨它没有notify信号,我认为这是一个设计上的疏忽 - 也就是说,在QML端提供任何以每个实例为基础初始化只读属性的方式。目前,正如我已经提到的,3个可能的解决方案要么带来额外的开销(有一个notify信号),要么有限制(在对象创建之前设置值 - 只适用于动态实例化),要么带来重大不便(使用setter和getter插槽而不实现实际的属性接口)。
ListModel.set()
修改它们。该属性是一个唯一的整数ID,需要从QML中设置,因为每个上下文都有自己持久化的ID管理器。 - dtech