我是QML的初学者,我试图遵循QtQuick标准组件的行为作为指导。
我想以TextEdit的工作方式实现用户输入组件。但现在我真的很困惑text
属性是如何实现的。
TextEdit的text
是只写的,并且始终显示其text
属性被分配/绑定的内容(如果存在)。
操作
运行QML
Window {
visible: true
property string foo: "foo"
TextEdit { text: foo }
}
在TextEdit中键入任何内容
预期文字始终显示“foo”,无法修改。
实际文字随您输入的内容而变化。
结论假设1是错误的。
text
属性设置为初始化时绑定的属性。
一旦用户编辑它,text
就会被分配给一个新值,从而破坏绑定。
操作
运行QML
Window {
visible: true
property string foo: "foo"
TextEdit { id: t1; text: foo; x: 0; }
TextEdit { id: t2; text: t1.text; x: 100 }
}
在t2中键入内容,然后在t1
中键入内容预期编辑完t2后,编辑t1将不再更改t2的显示。
实际 t2可以单独编辑。但是一旦再次编辑t1,t2的显示再次与t1绑定。
结论假设2是错误的。
TextEdit类似于internalText
,表示用户输入的内容。 TextEdit显示internalText
或text
最近更改的内容。
操作
运行QML
Window {
visible: true
property string foo: "foo"
TextEdit { id: t1; text: foo; x: 0; }
Button { x: 100; onClick: foo = "bar" } // A custom button
}
在t1中键入“blablabla”
点击按钮
在t1中键入“blablabla”
单击按钮,单击按钮,单击按钮一千次
可以编辑预期 t1,点击按钮后,显示屏将重置为“bar”。
实际第一次点击时显示设置为“bar”,之后点击该按钮完全没有效果。
结论假设3是假的......什么...... ??
在阅读QML Reference several times几次,尤其是Property Binding部分后,我不知道这样的属性如何可以写入和读取(也不像Angular的双向绑定)。我很困惑。
在做了实验3之后,我真的很困惑,有人可以解释它是如何工作的吗?
答案 0 :(得分:1)
绑定更像是元属性而不是实际值。一旦你想象它是如何在c ++方面起作用的话,这很容易理解。
使用信号和插槽实现绑定。简单的QML线
text: foo.text
作为示例将等同于以下c ++代码(简化):
// first: call the getter of text on foo, and the setter on this
this->setText(foo->text());
// second: connect the change signal of foo to this
connect(foo, SIGNAL(textChanged(QString)),
this, SLOT(setText(QString)));
正如您所看到的,绑定基本上是:"为我分配当前值,每当您的值发生变化时,请将我的值更新为您的值#34;。但是因为"这个"仍然拥有它自己的文本副本,你可以通过调用this->setText("something")
来修改它而不破坏绑定(或者用c ++术语 - 信号连接)
这也解释了第二个(和第一个)实验:每当你在GUI中更改t2的文本时,t2的内部文本就会更新。但是,由于绑定仍然存在,每次更改t1时,t1都会发出textChanged
信号,因此也会更新t2。
现在进行第3次实验,有点棘手。 c ++代码大大简化了,只解释了会发生什么,而不是它的实际工作方式。对于第三种情况,我们必须查看qml的javascript端。更具体:如何从javascript创建绑定:
// the qml line
text: foo
// is eqivalent to the js
t1.text = Qt.binding(function(){return foo;})
所以你并没有真正为t1.text
分配一个值,而是一个"绑定对象"。 (Qt.binding
函数做了一些魔法并返回这样的对象)这内部与上面的c ++代码相同,但有一点不同。将新值分配给t1.text
后,就像在按钮中一样,旧的绑定与信号连接一起被删除,同时用新值替换绑定对象。
因此,在按钮中的JS代码中,用值" bar"替换绑定对象,从而销毁它。从GUI编辑文本不会破坏绑定,因为只有内部值发生更改,并且实际上没有任何内容从QML分配给该属性。
编辑:现在,后续按钮点击不执行任何操作的原因是:按下按钮一次后,foo设置为" bar",这会触发textChanged
信号因此改变t1。但是,下次按下按钮并且foo再次设置为bar时,它什么都不做,因为它已经是" bar"。您不能通过将其设置为与现在相同的值来改变任何内容。想象一下这样的setter实现:
void setText(QString text) {
if(this->text == text)
return;
this->text = text;
emit textChanged(text);
}
如果您修改代码,例如:
Button { x: 100; onClick: foo = t1.text + "bar" }
它将始终工作并相应地更新foo,因为此表达式始终为foo生成新值。
我希望我能解释一下你能理解的行为。