我是QML的初学者,我试图遵循QtQuick的标准组件的行为作为指导。
我想以TextEdit的方式实现一个用户输入组件。但是现在我真的很困惑text属性是如何实现的。
假设1:
TextEdit的text是只写的,并且总是显示它的text属性被分配/绑定到什么,如果它存在的话。
实验1
操作
运行QML
Window {
visible: true
property string foo: "foo"
TextEdit { text: foo }
}在TextEdit中键入任何内容
期望文本总是显示"foo“,不能编辑。
实际的文本随您输入的内容而改变。
结论假设1是错误的。
假设2:
text属性设置为初始化时绑定的对象。一旦用户编辑了它,text就被分配给一个新的值,这个值破坏了绑定。
实验2
操作
运行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是错误的。
假设3:
TextEdit有类似于internalText的东西,它代表用户输入的内容。而TextEdit显示的是internalText或text,两者以最新的更改为准。
实验3
操作
运行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引用,特别是属性绑定部分之后,我不知道这种既可以写又能读的属性(也不像角的双向绑定)。我很困惑。
在做了实验3之后,我真的很困惑,有人能解释一下它是如何工作的吗?
发布于 2018-05-08 23:34:39
绑定更像是元属性,而不是实际值。一旦您从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)));正如您所看到的,绑定基本上是:“为我分配当前值,每当您的值发生变化时,将我的值更新到您的值”。但是由于"this“仍然有它自己的文本副本,所以您可以通过调用this->setText("something")来修改它,而不破坏绑定(或者用c++术语--信号连接)
这也解释了第二个(和第一个)实验:每当您在GUI中更改t2文本时,t2的内部文本就会被更新。但是,由于绑定仍然存在,所以每次更改t1时,t1都会发出textChanged信号,从而更新t2。
现在是第三个实验,有点棘手。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生成一个新的值。
我希望我能解释一下你能理解的行为。
https://stackoverflow.com/questions/50238806
复制相似问题