本文介绍了解决财产和功能“覆盖”在QML中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看起来,虽然QML支持重写属性和功能,但支持有点笨重。下面是一个示例代码片段:

  // T1.qml 
QtObject {
property int p:1
函数f(){返回1}
}

// T2.qml
T1 {
属性字符串p:blah
函数f(){returnblah}
}


//用法
T1 {
Component.onCompleted:{
var obj = this
for(var k in obj)console.log(k ++ typeof obj [k] ++ obj [k])
}
}

T2 {
Component.onCompleted:{
var obj = this
for(var k in obj)console.log(k ++ typeof obj [k] ++ obj [k])
}
}

行为的覆盖率是一致的 - 无论成员被覆盖多少次,即使你做了这样的事情,你总能找到正确的:

  QtObject {
property T1 p:T2 {}
Component.onCompleted:console.log(pp ++ pf())
}

尽管该属性是用T1类型声明的,但它引用了一个T2对象,因此输出结果显示为blah blah。



  T2 {
函数f(){返回1.5}
Component.onCompleted:{
console.log(f())
}
}

迭代T1的输出如预期:

  qml:objectName字符串
qml:p编号1
qml:objectNameChanged函数function(){[code]}
qml:pChanged函数function(){[code]}
qml:f function function(){[code]}

然而,T2的输出有点奇怪:

  qml:objectName string 
qml:p string blah
qml:p string blah
qml:objectNameChanged函数function(){[code ]}
qml:pChanged函数function(){[code]}
qml:f函数function(){[code]}
qml:pChanged函数function {[code]}
qml:f function function(){[code]}

它列出了两次重写的成员,但是,它似乎并不是一个来自基本类型,另一个来自派生 - 因为 p ($ k

  var obj = this 
for(var k in obj)if((k == =f)&& (typeof obj [k] ===function))console.log(obj [k]())

调用 f 函数输出blah两次 - 这同样适用于函数overrides。

我预计迭代派生对象会显示属性和函数两次,但其中的一个将来自基类型。让它们实际上重复,都指的是同一个成员似乎毫无意义和不合逻辑。在实例层次的覆盖提出了另一个成员,再次,所有三个参考最新的覆盖。所以在技术上甚至不可能手动选择覆盖。



所以我的问题是是否可以指定覆盖:

  //在T2.qml中 - 伪代码
属性字符串p:T1 :: p +blah//值为1 blah
f(){return T1 :: f()+blah} //返回1 blah



  //在T2.qml中
属性string p:p +blah//绑定循环,p没有引用T1的p
f(){return f()+blah} //堆栈溢出,f不引用T1的f


解决方案

找到一个简单而朴素的手动解决方案:

  // T1.qml 
QtObject {
函数f(){返回f_t1()}
函数f_t1(){return 1}
}

// T2.qml
T1 {
函数f(){返回f_t2()}
函数f_t2(){return f_t1()+bla h}
}

//用法
T2 {
函数f(){返回f_t2()+ 1.5}
Component.onCompleted:console .log(f())// outputs 1 blah 1.5
}

总之,已经为覆盖的继承的每个级别显式地命名了函数,并且为多态访问使用了未修饰的函数覆盖,因此现在派生类可以重用基类型实现。


It seems like although QML supports "overriding" of properties and functions, the support is somewhat clunky. Here is an example snippet:

// T1.qml
QtObject {
    property int p: 1
    function f() { return 1 }
}

// T2.qml
T1 {
    property string p: "blah"
    function f() { return "blah" }
}


// usage
T1 {
    Component.onCompleted: {
        var obj = this
        for (var k in obj) console.log(k + " " + typeof obj[k] + " " + obj[k])
    }
}

T2 {
    Component.onCompleted: {
        var obj = this
        for (var k in obj) console.log(k + " " + typeof obj[k] + " " + obj[k])
    }
}

The behavior of overrides is consistent - no matter how many times a member was overridden, you always get the right one, even if you do something like this:

QtObject {
    property T1 p : T2 {}
    Component.onCompleted: console.log(p.p + " " + p.f())
}

Although the property is declared with type T1, it references a T2 object, and thus the output says "blah blah".

It also works on a `per instance" basis:

T2 {
    function f() { return 1.5 }
    Component.onCompleted: {
       console.log(f())
    }
}

The output from iterating T1 is as expected:

qml: objectName string
qml: p number 1
qml: objectNameChanged function function() { [code] }
qml: pChanged function function() { [code] }
qml: f function function() { [code] }

However, the output for T2 is a little odd:

qml: objectName string
qml: p string blah
qml: p string blah
qml: objectNameChanged function function() { [code] }
qml: pChanged function function() { [code] }
qml: f function function() { [code] }
qml: pChanged function function() { [code] }
qml: f function function() { [code] }

It lists the "overridden" members twice, however, it doesn't seem like one is from the "base" type and the other from the "derived" - as both p's are strings.

var obj = this
for (var k in obj) if ((k === "f") && (typeof obj[k] === "function")) console.log(obj[k]())

Calling both f functions outputs "blah" twice - so the same applies for the function "overrides" as well.

I expected that iterating the "derived" object would show the property and function twice, but one of those would be from the base type. Having them practically duplicated, both referring to the same member seems pointless and illogical. Overriding at instance level puts yet another member, and once again, all three reference the latest override. So it is technically not possible to even pick the overrides manually.

So my question is whether it is possible to specify the overrides:

// in T2.qml - pseudocode
property string p: T1::p + "blah" //  value is "1 blah"
f() { return T1:: f() + "blah" } //  returning "1 blah"

Attempting to do it in the naive way results in an epic fail:

// in T2.qml
property string p: p + "blah" //  binding loop, p does not refer to T1's p
f() { return f() + "blah" } //  stack overflow, f does not refer to T1's f
解决方案

Found one simple and naive manual solution:

// T1.qml
QtObject {
    function f() { return f_t1() }
    function f_t1() { return 1 }
}

// T2.qml
T1 {
    function f() { return f_t2() }
    function f_t2() { return f_t1() + " blah " }
}

// usage
T2 {
    function f() { return f_t2() + 1.5}
    Component.onCompleted: console.log(f()) // outputs 1 blah 1.5
}

In short, have explicitly named function for every level of the "inheritance" that overrides, and use the non-decorated function override for polymorphic access, thus now the "base" type implementations can be reused by the derived.

这篇关于解决财产和功能“覆盖”在QML中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 16:19