Qt 如何从QML将属性绑定到单一对象属性

Qt 如何从QML将属性绑定到单一对象属性,qt,qml,qtquick2,property-binding,Qt,Qml,Qtquick2,Property Binding,有一个关于如何从单例对象属性绑定到QML属性的示例。但是,如果我们想将QML属性绑定到单例对象呢 这是singleton类的定义 class Singleton : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName) public: explicit Singleton(QObject *parent = nullptr); QString name() const;

有一个关于如何从单例对象属性绑定到QML属性的示例。但是,如果我们想将QML属性绑定到单例对象呢

这是singleton类的定义

class Singleton : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName)
public:
    explicit Singleton(QObject *parent = nullptr);
    QString name() const;
    void setName(const QString &name);
private:
    QString m_name;
};
关于QML

property string qmlName: textField.text
TextField {
    id: textField
}
我想将
textField.text
绑定到Singleton对象
name
属性。可以将其绑定到一个解决方案,如

onQmlNameChanged: {
    Singleton.name = qmlName;
}
但这实际上不是一个任务,因为这是一个任务


那么有没有一种更自然的绑定方式来绑定单例对象属性呢?

这就是属性绑定的基本功能,至少我假设它就是这样做的-它将相关变量的changed()信号连接到重新计算引用它们的绑定表达式上

因此,这在实践中具有约束力:

onQmlNameChanged: {
    Singleton.name = qmlName;
}
如果只执行一次分配,则只会出现问题,但如果分配附加到一个信号,它将按预期从绑定中不断更新

这将与Singleton.name:qmlName相同,不幸的是,QML语法不允许以这种形式执行此操作。因此,无论出于何种目的,您都有一个绑定,即使它使用不同的语法来实现它

事实上,这与QML在地毯下为您所做的工作应该没有太大区别。例如,绑定:

someProp:anotherProp+yetAnotherProp

是这样实现的:

function unnamed(this) { return this.anotherProp + this.yetAnotherProp }
anotherPropChanged.connect(function(this) { this.someProp = unnamed(this) })
yetAnotherPropChanged.connect(function(this) { this.someProp = unnamed(this) })
Component.onCompleted: Singleton.name = Qt.binding(function() { return qmlName })

显然,手动执行此操作相当麻烦,尤其是当表达式变得更复杂且引用更多对象时,因此QML正在为您执行此操作。

您可以尝试如下方式分配绑定:

function unnamed(this) { return this.anotherProp + this.yetAnotherProp }
anotherPropChanged.connect(function(this) { this.someProp = unnamed(this) })
yetAnotherPropChanged.connect(function(this) { this.someProp = unnamed(this) })
Component.onCompleted: Singleton.name = Qt.binding(function() { return qmlName })

它适用于普通的QML对象,但不确定它是否适用于单例类。无论如何,您可以在本节中阅读有关此方法的更多信息。

实际上不需要qmlName属性。只需
onEditingFinished:{Singleton.name=qmlName}
TextField
就可以完成这项工作。是的,不需要qmlName,我们也可以在TextField的文本更改信号上编写代码,但这也不是一个属性绑定。至于textChanged信号,除了“实时搜索”之外,您可能不想使用它,否则,如果你需要完整的单词,为什么要为每个更改的字母发送信号呢。至于属性绑定,@ddriver对此进行了详细解释,因此在本例中,您只需要喜欢“binding”一词。如果它在引擎盖下也这样做,那么有什么区别呢?是的,我还认为为每个更改的字母发送信号是多余的。是的,我喜欢“绑定”这个词,因为它有一些独特的功能。但它与以信号方式分配给属性不一样,我不确定这是属性绑定所做的。我不这么认为,因为qmlName必须更改,所以要执行Singleton.name=qmlName行。但另一方面,当我们绑定属性时,绑定的属性也会用绑定的属性初始化。因此,为了模拟属性绑定,我们还必须解决这个问题。第二,这在qmlName和Singleton.name之间建立了一个永久的关系,但是在属性绑定上,这种关系是脆弱的,我的意思是,如果我们为绑定的属性分配任何内容,属性绑定将被破坏。是的,这样就不会安排在组件完成时进行自动评估,您必须手动执行。是的,您还必须手动断开连接,这只有在使用
signal:expr
而不是
signal.connect(namedFoo)
时才可能,这样以后您就可以调用
signal.disconnect(namedFoo)
。手动执行绑定也意味着手动管理绑定。如果Felix建议的解决方案有效,你应该使用它,因为它会自动为你做所有这些事情。是的,看起来@Felix solution更准确。谢谢你加入线程。