【问题标题】:Slider element keeps resetting target value to slider's minimum value滑块元素不断将目标值重置为滑块的最小值
【发布时间】:2016-01-23 15:08:58
【问题描述】:

有一个问题的自包含示例:

Rectangle {
    id: rect
    width: 200
    height: 200
    property real v : 50
    onVChanged: console.log(v)
    Button {
        onClicked: scomp.createObject(rect)
    }
    Component {
        id: scomp
        Rectangle {
            id: sli
            anchors.fill: parent
            Column {
                Slider {
                    width: 200
                    minimumValue: 10
                    maximumValue: 100
                    value: rect.v
                    onValueChanged: rect.v = value
                }
                Button {
                    onClicked: sli.destroy()
                }
            }
        }
    }
}

基本上,每次创建滑块组件以修改v 时,它都会将其设置为滑块的最小值。请注意,滑块仍然可以正常工作以修改该值,并且v 在滑块关闭后将保持其正确值,但再次打开时,该值再次损坏。

为什么会发生这种情况,如何预防?似乎出于某种可解释的原因,滑块的 value 属性暂时假定了其 minimumValue 值,但这看起来并不合适。也许是一个错误?即使在设置最小值之前移动了value: rect.v,滑块也不会真正假定正确的初始值。

【问题讨论】:

    标签: qt binding qml qtquick2 qtquickcontrols


    【解决方案1】:

    这不是Slider 中的错误,这是您对它的使用:

    onValueChanged: rect.v = value
    

    如果再添加一些调试语句:

    qml: maximumValue = 100 value = 0
    qml: minimumValue = 10 value = 10
    qml: value = 10
    qml: v = 10
    void __cdecl QQuickRangeModel::setValue(double) 10
    qml: in Component.onCompleted of Slider: value = 10 minimumValue = 10 maximumValue = 100
    

    在它有机会完成加载之前,您已经将其value 分配给了v。正确的解决方案取决于您没有提到的要求。例如,一种解决方案是在Slider 中指定默认值,并将v 绑定到value

    v: slider ? slider.value : 0
    

    执行顺序好像设计的不好

    How would you design it?


    要使用 Qt Quick Controls 2 中的 Slider 更新此答案,您应该使用 moved() signal 来响应被拖动的滑块。为此目的使用onValueChanged 通常会导致问题。

    【讨论】:

    • 更好的解决方案是先设置值,如果超出范围,值本身可以推送最小值和最大值,这将更合适 - 滑块适应使用场景而不是生成虚假值变化。
    • 如果改进后的滑块和你说的一样好,为什么不将改进贡献回你使用的设计不佳的产品中呢?
    • 据我所见,它正在按预期工作(即记录在案),是的。如果您认为应该以不同的方式进行,Gerrit 就是您的理想去处。但似乎大多数人宁愿抱怨和批评而不提出实际的解决方案,声称这个过程太繁琐(这很奇怪,因为任何可以使用 Git 并在互联网上创建帐户的人都可以很快上手)。
    • @Mitch - 大多数人都会抱怨,我坐下来解决了这个问题。该文档没有提及限制使用场景的寄生值变化。如果您是这样一个敬业的社区成员,请继续修复股票Slider - 这是我的代码,您可以借用寄生值更改解决方法,我不寻求信用或任何交换:pastebin.com/i4wzvELR
    • 谢谢,但我的滑块没有问题,我有自己的事情要做。
    【解决方案2】:

    没有深入研究Slider元素的实现,似乎实现顺序设计得不好,初始值为0.0,因此将最小值设置为更高的值也会推高该值。并且 value 是否绑定到高于最小值也没有关系,由于评估的顺序,设置最小值时 value 始终为 0.0,因此在这种格式下,目标值将始终损坏为滑块的最小值。

    我想出的解决方案通过延迟目标值绑定来避免这种行为,它可以工作,但它不是那么漂亮,所以我仍然对其他解决方案持开放态度,同时 Qt 家伙 - 如果你看到这个你可能想要修复Slider:

    Slider {
        width: 200
        minimumValue: 10
        maximumValue: 100
        value: rect.v
        Component.onCompleted: valueChanged.connect(function(){ rect.v = value})
    }
    

    这种格式最初还是将滑块值推到最小值,但是此时设置目标值的绑定还不存在,只有在滑块值取正确值后才创建。

    【讨论】:

    • 您根本不应该依赖valueChanged,因为像所有其他处理程序一样,每次值更改都会调用,甚至是初始分配。糟糕的设计选择?你可以对此争论,但这就是它目前的工作方式。而是将值绑定到滑块值:使用滑块更新值。类似this.
    • @BaCaRoZzo 您的代码很荒谬,显然调整后滑块被破坏,将目标值绑定到滑块值是问题的最糟糕的“解决方案”,实际上甚至不是解决方案。如果滑块被正确实现,将滑块值设置为目标值不会循环回目标值,因为值是相同的。滑块中存在寄生值变化,是的,寄生意外行为是糟糕的设计。正是这种糟糕的设计阻止了组件以最干净、最合乎逻辑的方式使用。
    • 除了功能之外,您的解决方案实际上建议将数据绑定到 UI,这本身就是非常糟糕的设计。 UI 绑定到数据,数据不应该依赖于 UI。 UI 根据需要随时提供,以可视化数据或与数据交互。
    • 绑定数据和UI不好,总的来说,你显然是对的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    相关资源
    最近更新 更多