Временное значение свойства QML без полного нарушения привязки
В QML (по крайней мере, до версии 5.6 1) привязки свойств нарушаются после назначения нового значения в контексте JavaScript:
Item {
property bool sourceBool: <some changing value e.g. from C++ code>
property bool boundBool: sourceBool
function reassignBool() {
boundBool = true;
}
}
однажды reassignBool
называется, boundBool
будет true
независимо от состояния sourceBool
,
Я хотел бы иметь возможность назначить временное значение свойству, которое не нарушит первоначальную привязку; временное значение будет сохраняться до тех пор, пока NOTIFY
срабатывают сигналы, связанные с исходной привязкой, после чего свойство привязки снова будет отражать значение, вычисленное привязкой.
В качестве примера использования предположим, что у меня есть кнопка, которую я не хочу, чтобы пользователь мог нажимать два раза подряд, и которая включена или отключена согласно некоторому набору правил:
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>
}
}
... но, конечно, как только я восстановлю привязку, так как condition1
еще не стал false
, enabled
станет true
снова.
Я полагаю, я мог бы создать какой-то Connections
объект, который соединит NOTIFY
сигнал (ы), связанные с <condition1>
к обработчику, который будет вызывать Qt.binding
, затем.... удалить Connections
объект, я полагаю. Но это кажется довольно сложным и не элегантным.
Есть ли способ обеспечить enabled
установлен в false
немедленно, затем снова привязать к NOTIFY
сигналы для <condition1>
а также <condition2>
как только какой-либо из этих сигналов испускается?
1 Я не совсем уверен, как назначения влияют на привязки в 5.7, но я знаю, что присвоение значения свойству не нарушает привязку автоматически. Так что это может просто сработать автоматически из 5.7.
1 ответ
Это должно быть довольно простым для достижения с помощью QML Binding
type, который отлично подходит для временного переопределения привязки, не разрушая ее (и это было еще с версии 5.6!)
Вам понадобится переменная или свойство, которое вы можете использовать в when
свойство типа Binding. В приведенном ниже примере я использовал 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
}
}