如何获得涉及QML MouseAreas的声明性双向绑定? [英] How do I have declarative, bidirectional bindings involving QML MouseAreas?
问题描述
我创建了一个具有转盘和自定义控件的QML UI.自定义控件基本上是带有MouseArea
的进度条,允许用户单击它来设置值.正如Qt的属性绑定文档指出的那样,从MouseArea
单击处理程序中的Javascript分配给自定义控件的值,我将失去它和拨盘之间的声明性绑定.
I've created a QML UI that has a dial and a custom control. The custom control is basically a progress bar with a MouseArea
to allow the user to set the value by clicking it. As Qt's property binding docs point out, as soon as I assign to the custom control's value from Javascript in the MouseArea
click handler, I lose the declarative binding between it and the dial.
在QML层次结构中,是否可以使此绑定双向,甚至更好,以将两个控件的值链接到单个控件上的单个值?并且可以使用声明性语法来做到这一点,这样我就不会在每个控件中都有复杂的事件处理程序代码吗?
Is it possible to make this binding bidirectional, or even better, to link the values of both controls to a single value above both of them in the QML hierarchy? And is it possible to do this with declarative syntax so I don't have complex event handler code in every control?
import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.2
import QtQuick.Shapes 1.0
Window {
id: window
visible: true
width: 800
height: 200
readonly property int range: 10
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: 5
Dial {
id: dial1
live: true
from: 0
to: window.range
stepSize: 1
snapMode: Dial.SnapAlways
}
Control {
id: dut
implicitWidth: 200
implicitHeight: 50
property int range: window.range
property int value: dial1.value
onValueChanged: {
console.log("New value: " + value);
}
Rectangle {
width: parent.width
height: parent.height
color: Qt.rgba(0,0,0,0)
border.color: Qt.rgba(0,0,0,1)
border.width: 1
}
Rectangle {
width: parent.width * dut.value/dut.range
height: parent.height
color: Qt.rgba(0,0,0,1)
}
MouseArea {
anchors.fill: parent
onClicked: {
dut.value = Math.round(mouseX/width * dut.range);
}
}
}
}
}
请注意,如果我颠倒关系,即.具有dial1.value: dut.value
,则绑定不会中断(尽管它不是双向的).
Note that if I reverse the relationship ie. have dial1.value: dut.value
, then the binding isn't broken (although it's not quite bidirectional).
我意识到这个示例从根本上重塑了滚动条,但是我正在尝试以更复杂的控件进行工作,对于这些控件,值之间的声明性关系将使生活变得更加轻松.
I realise that this example basically reinvents the scrollbar, but I'm trying to work my way up to more complex controls, for which declarative relationships between values would make life much easier.
评论中的阐述:我不了解,但想要了解的是如何对其他QML组件进行处理.例如,使用Dial
,我可以将其value
属性设置为绑定到其他组件的属性,并且单击表盘不会删除该绑定.我不必迷上它的鼠标事件就可以做到这一点.尽管从源头上了解了如何完成此操作,但我实际上离了解它还很近.
Elaboration from a comment: What I don't understand, but want to, is how it's done for other QML components. For example, with a Dial
I can set its value
property to be bound to some other component's property, and clicking on the dial doesn't remove that binding. I don't have to hook into its mouse events to do that. Despite looking through the source for how this is done, I'm not really any closer to understanding it.
关于QML中的双向属性绑定还有其他问题,但是我无法将其应用于我的问题,因为(a)我真的非常想要声明性的东西,并且(b)MouseArea
属性和事件似乎不适用于Binding
对象(例如,我无法弄清楚如何整合这两种方法).
There are other questions about bidirectional property bindings in QML, but I haven't been able to apply them to my problem because (a) I really, really want something declarative, and (b) the MouseArea
properties and events don't seem to work well with Binding
objects (as in, I can't figure out how to integrate the two things).
推荐答案
我会这样做:
import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.2
import QtQuick.Shapes 1.0
Window {
id: window
visible: true
width: 800
height: 200
readonly property int range: 10
property int commonValue
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: 5
Dial {
id: dial1
live: true
from: 0
to: window.range
stepSize: 1
snapMode: Dial.SnapAlways
onValueChanged: {
commonValue = dial1.value
console.log("New value: " + value);
}
}
Rectangle {
width: 200
height: 50
color: Qt.rgba(0,0,0,0)
border.color: Qt.rgba(0,0,0,1)
border.width: 1
MouseArea {
anchors.fill: parent
onClicked: {
commonValue = Math.round(mouseX/width * window.range)
dial1.value = commonValue
}
}
Rectangle {
width: parent.width * window.commonValue/window.range
height: parent.height
color: Qt.rgba(0,0,0,1)
}
}
}
}
这篇关于如何获得涉及QML MouseAreas的声明性双向绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!