QML中是否存在多态和/或对象指针?我有一个班级A
,有五个不同类别的成员,其中一个在任何特定时刻都可见。我在A
中的属性依赖于可见成员中的属性(在所有成员中称为相同的东西)。
目前,我正在使用以下策略计算A
中的所有此类属性:
import QtQuick 2.7
Rectangle {
property int a: member1.visible ? member1.alpha + member1.beta :
member2.visible ? member2.alpha + member2.beta :
member3.visible ? member3.alpha + member3.beta :
member4.visible ? member4.alpha + member4.beta :
member5.visible ? member5.alpha + member5.beta :
0
property int b: member1.visible ? member1.gamma * member1.delta :
member2.visible ? member2.gamma * member2.delta :
member3.visible ? member3.gamma * member3.delta :
member4.visible ? member4.gamma * member4.delta :
member5.visible ? member5.gamma * member5.delta :
0
// Exactly one of these members have its visible-property set to true
MySubClass1 {id: member1}
MySubClass2 {id: member2}
MySubClass3 {id: member3}
MySubClass4 {id: member4}
MySubClass5 {id: member5}
}
感觉就像它使用了比必要更多的代码,并且它不是非常易于维护,因为它很容易出错,因为我必须更新A中所有属性的表达式,如果我想添加或删除构件。
理想情况下(从做很多C ++编程的背景来看),我希望能够做到这样的事情:
import QtQuick 2.7
Rectangle {
property <property-type> visibleMember:
member1.visible ? member1 :
member2.visible ? member2 :
member3.visible ? member3 :
member4.visible ? member4 :
member5.visible ? member5 :
0 // Shouldn't happen
property int a: visibleMember.alpha + visibleMember.beta
property int b: visibleMember.gamma * visibleMember.delta
MySubClass1 {id: member1}
MySubClass2 {id: member2}
MySubClass3 {id: member3}
MySubClass4 {id: member4}
MySubClass5 {id: member5}
}
为了减少需要编写的代码量并增加可维护性,其中visibleMember
将成为指针或某种对象的引用。或者甚至可能:
import QtQuick 2.7
Rectangle {
property <property-type> visibleMember: NULL
property int a: visibleMember !== NULL ? visibleMember.alpha + visibleMember.beta : 0
property int b: visibleMember !== NULL ? visibleMember.gamma * visibleMember.delta : 0
}
并从类外部设置visibleMember
(例如通过其父级),并以这种方式动态创建对象(如果可能),然后将其分配给visibleMember
,而不是拥有可以分配给visibleMember
的所有可能对象作为A
中的潜在成员。
但是,我不确定<property-type>
是什么,或者你是否可以像这样分配一个对象指针{(1)是否存在对象指针/引用,然后可以检查看它是否是visibleMember
指针。至少是我试图以某种方式实现的事情的一部分吗?
答案 0 :(得分:1)
如果所有类都继承了相同的基类,那么可以说QtObject
可以轻松地将其用作属性类型。
您仍然可以访问基类中不存在的属性,因为具体对象保留其原始元信息。
然后,此元信息用于评估绑定。
如果您尝试访问未在要访问它的具体对象中定义的属性,它将评估为undefined
。如果您尝试访问子属性,则会发出警告。
如果您没有任何公共基类,因为它可能也是string
或int
,您可以使用var
作为该属性的数据类型。
出于性能原因,建议使用最接近的拟合/可能的数据类型。如果用于该属性的数据类型已具有您要在其中访问的属性,则可以优化绑定。
假设我们的基类是MyBaseClass
,那么你可以写:
import QtQuick 2.7
Rectangle {
property MyBaseClass visibleMember:
member1.visible ? member1 :
member2.visible ? member2 :
member3.visible ? member3 :
member4.visible ? member4 :
member5.visible ? member5 :
null // Shouldn't happen
property int a: visibleMember.alpha + visibleMember.beta
property int b: visibleMember.gamma * visibleMember.delta
MySubClass1 {id: member1}
MySubClass2 {id: member2}
MySubClass3 {id: member3}
MySubClass4 {id: member4}
MySubClass5 {id: member5}
}
如果该基类还具有预定义属性alpha, beta, gamma, delta
,则可以优化a
和b
的绑定。
当然,您也可以从外部设置该属性,因为您已在组件的根节点中公开该属性。
答案 1 :(得分:1)
为什么你需要这样做?看起来你正在滥用QML语言,你肯定会遇到性能问题。
请花点时间尝试了解QML语言及其与C ++的区别。
首先请注意
Rectangle {
MySubClass1 {id: member1}
MySubClass2 {id: member2}
}
绝对不等同于:
struct MyStruct: public Rectangle
{
MySubClass1 member1;
MySubClass2 member2;
}
但它更像是这样:
struct MyStruct: public Rectangle
{
MyStruct()
{
children.insert("member1", new MySubClass1);
children.insert("member2", new MySubClass2);
}
map<string, void *> children;
}
如果您在特定时间只需要会员,您可以这样做:
// MyComponent.qml
Rectangle {
id: root
property var visibleMember: InitialMember{} // If you can, replace var by the closest fitting data type
property int a: visibleMember.alpha + visibleMember.beta
property int b: visibleMember.gamma * visibleMember.delta
function change1() {
visibleMember.destroy();
var component = Qt.createComponent("MySubClass1.qml");
var object = component.createObject(root);
visibleMember = object;
}
function change2() {
visibleMember.destroy();
var object = Qt.createQmlObject('import QtQuick 2.0; MySubClass2 {}', root);
visibleMember = object;
}
}
您还可以静态或动态地从外部设置visibleMember
:
MyComponent { // Assumming the code above is in MyComponent.qml
visibleMember: SomethingElse {}
}
注意:如果这是MyComponent
应该使用的方式,您可以删除change1()
,change2()
甚至InitialMember{}
来自MyComponent.qml
。
与上述相同,但使用Loader
代替Qt.createComponent()
Rectangle {
id: root
property var visibleMember: loader.item // If you can replace var by the closest fitting data type
property alias source: loader.source // If you want to expose the loader source
property int a: visibleMember.alpha + visibleMember.beta
property int b: visibleMember.gamma * visibleMember.delta
function change1() {
loader.source = "MySubClass1.qml";
}
function change2() {
loader.source = "MySubClass2.qml";
}
Loader {
id: loader
}
}