在QML中(至少在版本5.61之前),一旦在JavaScript上下文中分配了新值,属性绑定(bind)就会中断:
Item {
property bool sourceBool: <some changing value e.g. from C++ code>
property bool boundBool: sourceBool
function reassignBool() {
boundBool = true;
}
}
调用
reassignBool
后,无论boundBool
的状态如何,true
均为sourceBool
。我希望能够为不会破坏原始绑定(bind)的属性分配一个临时值;临时值将一直存在,直到触发了与原始绑定(bind)相关联的任何
NOTIFY
信号为止,此时绑定(bind)属性将再次反射(reflect)由绑定(bind)计算出的值。作为一个示例用例,假设我有一个我不希望用户连续按下两次的按钮,并且该按钮根据某些规则启用或禁用:
MyButton {
id: onceOnlyButton
// Suppose the QML type `MyButton` provides a boolean property
// called `enabled` that greys out the button and prevents it from
// being clicked when `false`.
enabled: <condition1> && <scondition2>
onClicked: {
<schedule some asynchronous work>
}
}
假设单击该按钮时,
<condition1>
最终将变为false
,因此该按钮最终将被适本地禁用-但不会立即被禁用。所以我想做如下的事情:
....
onClicked: {
enabled = false
<schedule some asynchronous work>
enabled = Qt.binding(function() {
return <condition1> && <condition2>
}
}
...但是,当然,一旦我重新建立绑定(bind),由于
condition1
尚未变为false
,因此enabled
将再次变为true
。我想我可以创建某种
Connections
对象,该对象将与NOTIFY
相关联的<condition1>
信号连接到将调用Qt.binding
的处理程序,然后....我想删除Connections
对象。但是,这似乎很复杂且微不足道。是否有任何方法可以确保立即将
enabled
设置为false
,然后在发出任何这些信号后立即将其重新绑定(bind)到NOTIFY
和<condition1>
的<condition2>
信号?1我不太确定赋值如何影响5.7中的绑定(bind),但是我知道assigning a value to a property does not automatically break the binding。因此,这可能会自动在5.7中开箱即用。
最佳答案
这对于使用QML Binding
类型来实现应该是很直接的,它非常适合临时覆盖绑定(bind)而不破坏它(并且从5.6版开始就存在!)
您将需要一个可以在Binding类型的when
属性中使用的变量或属性。在下面的示例中,我使用了timer.running
,因为此处安排的异步工作只是一个计时器。
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
property bool condition1: true
property bool condition2: true
Button {
id: onceOnlyButton
enabled: condition1 && condition2
Binding on enabled {
when: timer.running
value: false
}
onClicked: {
timer.start()
}
text: "onceOnlyButton"
}
// stuff below is just for demonstration
Button {
anchors.left: onceOnlyButton.right
text: "toggle Condition1\n(to prove binding still intact)"
onClicked: condition1 = !condition1
}
Timer {
id: timer
interval: 2000
running: false
repeat: false
onTriggered: condition1 = false
}
}
如果您没有变量,则可以使用它来确定异步工作是否仍在继续(例如我的
timer.running
),那么您将需要创建一个变量,如下面的forceButtonDisable
属性。这使它看起来更加复杂,因此让我们将其包装在一个新的可重用组件中:OnceOnlyButton.qml ##
import QtQuick 2.7
import QtQuick.Controls 2.0
Item {
id: control
property alias text: button.text
property bool enabled
property bool forceButtonDisable: false
signal clicked()
onEnabledChanged: forceButtonDisable = false
width: button.implicitWidth
height: button.implicitHeight
Button {
id: button
width: control.width
height: control.height
enabled: control.enabled
Binding on enabled {
when: control.forceButtonDisable
value: false
}
onClicked: {
control.forceButtonDisable = true
control.clicked()
}
}
}
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
property bool condition1: true
property bool condition2: true
// once clicked, the button is temporarily disabled until original binding expression results in a different value
OnceOnlyButton {
id: onceOnlyButton
text: "onceOnlyButton"
enabled: condition1 && condition2
onClicked: timer.start()
}
// stuff below is just for demonstration
Button {
anchors.left: onceOnlyButton.right
text: "toggle Condition1\n(to prove binding still intact)"
onClicked: condition1 = !condition1
}
Timer {
id: timer
interval: 2000
running: false
repeat: false
onTriggered: condition1 = false
}
}
关于qt - QML属性的临时值,而不会完全破坏绑定(bind),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38880744/