我创建了一个具有拨号和自定义控件的QML用户界面。自定义控件基本上是一个带MouseArea
的进度条,允许用户通过单击来设置值。作为Qt的property binding docs point out,只要我在MouseArea
点击处理程序中从Javascript分配自定义控件的值,我就会失去它与拨号盘之间的声明性绑定。 / p>
是否有可能使这种绑定双向,甚至更好,将两个控件的值链接到QML层次结构中它们上面的单个值?是否可以使用声明性语法来完成此操作,因此我不会在每个控件中都有复杂的事件处理程序代码?
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
,然后绑定没有被破坏(虽然它不是很双向)。
我意识到这个例子基本上重新发明了滚动条,但是我试图通过更复杂的控制来实现这一点,因为值之间的声明性关系会让生活更轻松。
评论中的详细说明:我不了解但想要了解的是,其他QML组件是如何完成的。例如,使用Dial
我可以将其value
属性设置为绑定到某个其他组件的属性,并且单击拨号不会删除该绑定。我不必为了做到这一点而挂钩它的鼠标事件。尽管我们已经了解了如何做到这一点,但我并没有更接近理解它。
关于QML中的双向属性绑定还有其他问题,但是我还没有能够将它们应用到我的问题中,因为(a)我真的,真的想要一些声明性的东西,以及(b){{1} }属性和事件似乎不适用于MouseArea
个对象(因为,我无法弄清楚如何整合这两个东西)。
答案 0 :(得分:1)
我会这样做的:
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)
}
}
}
}
答案 1 :(得分:0)
MouseArea {
id: mouseArea
anchors.fill: dut
}
Binding {
target: dut
property: 'value'
value: Math.round(mouseArea.mouseX/mouseArea.width * dut.range);
when: mouseArea.pressed && mouseArea.containsMouse
}
请注意when
上的Binding
属性意味着它只在满足这些条件时才作为绑定激活,即。鼠标位于该区域上方,其中一个是"accepted buttons" is pressed。
这个不意味着当条件不满足时值会恢复,只是当值不满足时该值会停止更新。但是,如果您在其他地方有另一个绑定活动,那么可能会导致该值“快速恢复”,因为当Binding
停止应用时,它将“接管”。
根据您使用的其他组件,这可能甚至不够,您可能需要在C ++中实现属性,以使它们按预期工作。