如何在可重用的 QML 组件中保留绑定?
How to preserve bindings in a re-usable QML component?
我试图在我的滑块组件中保留双重绑定逻辑,这样它的行为与内置的一样 Slider
:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Window {
ColumnLayout {
SimpleSlider { id: sslider0; value: .3 }
SimpleSlider { id: sslider1; value: 1 - sslider0.value }
Slider { id: slider0; value: .3 }
Slider { id: slider1; value: 1 - slider0.value }
}
}
不幸的是,它没有:
这是我的 SimpleSlider.qml
:
import QtQuick 2.4
Item {
id: simple_slider
property real value: .5
property real min_value: 0
property real max_value: 1
width: childrenRect.width
height: childrenRect.height
function linear(a, b, x) { return (x - a) / (b - a) }
function mix(a, b, x) { return a * (1 - x) + b * x }
FontMetrics { id: fontMetrics }
Rectangle {
id: main_box
width: Math.max(txt_label.width + 10, 50)
height: fontMetrics.height + 10
radius: 2
color: "darkgrey"
}
Rectangle {
id: filled_box
width: linear(min_value, max_value, value) * main_box.width
height: main_box.height
radius: main_box.radius
color: "orange"
}
Text {
id: txt_label
text: value.toFixed(3)
anchors.centerIn: main_box
}
MouseArea {
property real xval: simple_slider.value
id: drag_slider
anchors.fill: parent
onPositionChanged: xval = get_value_from_pos(mouse.x)
function get_value_from_pos(x) {
var v = Math.min(Math.max(linear(0, main_box.width, x), 0), 1)
return mix(min_value, max_value, v)
}
}
Binding {
target: simple_slider
property: "value"
value: drag_slider.xval
}
}
原因很明显:我在这里覆盖绑定:onPositionChanged: xval = get_value_from_pos(mouse.x)
(并由 QT_LOGGING_RULES="qt.qml.binding.removal.info=true"
确认)
但是虽然我确定了问题的核心,但我不确定如何处理它。
可能有一个扭曲的设计,我会使用位置更改状态将其变成基于声明的形式,但是当我的滑块也接受来自 [=16= 的值时,我会遇到类似的问题](这将需要在其 onAccepted
回调中以类似的方式更新值)。
JarMan 的提示很好。我试图解决您示例中的双向绑定问题,但没有成功。因此,我向您展示了样式化的标准滑块:
这是我的 SimpleSlider.qml
:
import QtQuick 2.15
import QtQuick.Templates 2.15 as T
T.Slider {
id: slider
width: 200
height: 40
background: Rectangle {
color: "darkgrey"
Rectangle {
width: slider.visualPosition * parent.width
height: parent.height
color: "orange"
}
}
Text {
text: slider.value.toFixed(3)
anchors.centerIn: slider
}
}
已编辑 SimpleSlider.qml:
import QtQuick 2.15
import QtQml 2.15
Item {
id: simple_slider
property real value: .5
property real tempValue: value
property real min_value: 0
property real max_value: 1
width: childrenRect.width
height: childrenRect.height
function linear(a, b, x) { return (x - a) / (b - a) }
function mix(a, b, x) { return a * (1 - x) + b * x }
FontMetrics { id: fontMetrics }
Rectangle {
id: main_box
width: Math.max(txt_label.width + 10, 50)
height: fontMetrics.height + 10
radius: 2
color: "darkgrey"
}
Rectangle {
id: filled_box
width: linear(min_value, max_value, tempValue) * main_box.width
height: main_box.height
radius: main_box.radius
color: "orange"
}
Text {
id: txt_label
text: tempValue.toFixed(3)
anchors.centerIn: main_box
}
MouseArea {
///property real xval: simple_slider.value
id: drag_slider
anchors.fill: parent
onPositionChanged: tempValue = get_value_from_pos(mouse.x)
onReleased: tempValue = Qt.binding(function() { return value })
function get_value_from_pos(x) {
var v = Math.min(Math.max(linear(0, main_box.width, x), 0), 1)
return mix(min_value, max_value, v)
}
}
Binding on value {
when: drag_slider.pressed
value: tempValue
restoreMode: Binding.RestoreBinding
}
}
我试图在我的滑块组件中保留双重绑定逻辑,这样它的行为与内置的一样 Slider
:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Window {
ColumnLayout {
SimpleSlider { id: sslider0; value: .3 }
SimpleSlider { id: sslider1; value: 1 - sslider0.value }
Slider { id: slider0; value: .3 }
Slider { id: slider1; value: 1 - slider0.value }
}
}
不幸的是,它没有:
这是我的 SimpleSlider.qml
:
import QtQuick 2.4
Item {
id: simple_slider
property real value: .5
property real min_value: 0
property real max_value: 1
width: childrenRect.width
height: childrenRect.height
function linear(a, b, x) { return (x - a) / (b - a) }
function mix(a, b, x) { return a * (1 - x) + b * x }
FontMetrics { id: fontMetrics }
Rectangle {
id: main_box
width: Math.max(txt_label.width + 10, 50)
height: fontMetrics.height + 10
radius: 2
color: "darkgrey"
}
Rectangle {
id: filled_box
width: linear(min_value, max_value, value) * main_box.width
height: main_box.height
radius: main_box.radius
color: "orange"
}
Text {
id: txt_label
text: value.toFixed(3)
anchors.centerIn: main_box
}
MouseArea {
property real xval: simple_slider.value
id: drag_slider
anchors.fill: parent
onPositionChanged: xval = get_value_from_pos(mouse.x)
function get_value_from_pos(x) {
var v = Math.min(Math.max(linear(0, main_box.width, x), 0), 1)
return mix(min_value, max_value, v)
}
}
Binding {
target: simple_slider
property: "value"
value: drag_slider.xval
}
}
原因很明显:我在这里覆盖绑定:onPositionChanged: xval = get_value_from_pos(mouse.x)
(并由 QT_LOGGING_RULES="qt.qml.binding.removal.info=true"
确认)
但是虽然我确定了问题的核心,但我不确定如何处理它。
可能有一个扭曲的设计,我会使用位置更改状态将其变成基于声明的形式,但是当我的滑块也接受来自 [=16= 的值时,我会遇到类似的问题](这将需要在其 onAccepted
回调中以类似的方式更新值)。
JarMan 的提示很好。我试图解决您示例中的双向绑定问题,但没有成功。因此,我向您展示了样式化的标准滑块:
SimpleSlider.qml
:
import QtQuick 2.15
import QtQuick.Templates 2.15 as T
T.Slider {
id: slider
width: 200
height: 40
background: Rectangle {
color: "darkgrey"
Rectangle {
width: slider.visualPosition * parent.width
height: parent.height
color: "orange"
}
}
Text {
text: slider.value.toFixed(3)
anchors.centerIn: slider
}
}
已编辑 SimpleSlider.qml:
import QtQuick 2.15
import QtQml 2.15
Item {
id: simple_slider
property real value: .5
property real tempValue: value
property real min_value: 0
property real max_value: 1
width: childrenRect.width
height: childrenRect.height
function linear(a, b, x) { return (x - a) / (b - a) }
function mix(a, b, x) { return a * (1 - x) + b * x }
FontMetrics { id: fontMetrics }
Rectangle {
id: main_box
width: Math.max(txt_label.width + 10, 50)
height: fontMetrics.height + 10
radius: 2
color: "darkgrey"
}
Rectangle {
id: filled_box
width: linear(min_value, max_value, tempValue) * main_box.width
height: main_box.height
radius: main_box.radius
color: "orange"
}
Text {
id: txt_label
text: tempValue.toFixed(3)
anchors.centerIn: main_box
}
MouseArea {
///property real xval: simple_slider.value
id: drag_slider
anchors.fill: parent
onPositionChanged: tempValue = get_value_from_pos(mouse.x)
onReleased: tempValue = Qt.binding(function() { return value })
function get_value_from_pos(x) {
var v = Math.min(Math.max(linear(0, main_box.width, x), 0), 1)
return mix(min_value, max_value, v)
}
}
Binding on value {
when: drag_slider.pressed
value: tempValue
restoreMode: Binding.RestoreBinding
}
}