我有一个C++对象暴露给QML,带有"一种"只读属性,除了属性仍然需要从QML设置,所以它有一个WRITE
定义的方法,但除了最初的强制设置,它永远不会改变,所以我觉得这NOTIFY
是多余的,因为它在使用时已经设置了该值,并且它永远不会改变.
然而,QML并没有分享我的感觉,并且无论它喷出"表达式取决于非NOTIFYable属性"警告.
由于使用属性实例化对象的方式是设置该值的唯一适用方式,因此不可能使用可调用的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它会改变,因此会抱怨它没有通知信号,IMO是一个设计监督 - 这是,没有提供任何方法在每个实例的基础上初始化QML端的只读属性.目前,正如我已经提到的,3种可能的解决方案要么有开销(有通知信号),限制(在创建对象之前设置值 - 仅适用于动态实例化)或主要不便(使用setter和getter slot而不实现实际属性接口).