QML相关bug记录

请添加图片描述
更多资讯、知识,微信公众号搜索:“上官宏竹”。


浮点赋值会截断

浮点数据直接付给QML中的整型属性,则会直接截断。比如一个属性int a,将一个40.0f的浮点型赋值给a,则a可能会为39。因为40.0f,实际表示为39.99999xxx等。此时需要向上取整或者四舍五入(Math.round(value)

属性绑定相关

结论

属性绑定时,被绑定的属性的更新时机是在源属性有变化的时候,执行更新的。

过程

下面的代码中contentItem: STextInputtext其实是与rootItem.value绑定的(text: cusSpinBox.textFromValue(rootItem.value, cusSpinBox.locale))。而属性绑定会有一个特性,只有当源属性变化时才会触发绑定的计算。
那么下面这段代码的被调用就值得考量了:
它的作用是获取SpinBoxcontentItem: STextInput的输入值,改成对应的value,即从text到value的转化。
这里有一个操作就是要判断from和to的范围,让输入的数值在这个范围内显示,当前默认最大值为2.0。
那么这里有一个问题就是,当第一次设置超过2.0的值后,再次再设置超2.0的值后,contentItem: STextInput对应的值不再显示正确范围内的值。比如,输入5后,再输入20,第一次输入5后,contentItem: STextInput会更新到2.0,而再次输入20后,contentItem: STextInput就不会有更新,还是输入的20这个值。
这个问题的关键就是,第一输入5后,rootItem.value的值从其他值被改为2.0,再次输入20后,rootItem.value的值还是被改为2.0,这等于没有变化。那么text: cusSpinBox.textFromValue(rootItem.value, cusSpinBox.locale)那么这段属性绑定的代码就不会再次计算,显然就不会更新contentItem: STextInput

valueFromText: function(text, locale) {
    let tmpValue = Number.fromLocaleString(locale, text)
    console.log("valueFromText : " + text + " => " + tmpValue+" from: "+getFrom()+" to: "+getTo())

    if (tmpValue > getTo()) {
        tmpValue = getTo()
    }
    if (tmpValue < getFrom()) {
        tmpValue = getFrom()
    }
    let realValue = tmpValue.toFixed(decimals)
    rootItem.value = realValue
    console.log("2 realValue : " + realValue)
    return realValue
}

完整的有问题的代码如下:

Item {
    id: rootItem
    height: 22
    implicitWidth: 80
    anchors.verticalCenter: parent.verticalCenter

    property int decimals: 1
    property real from: -1.0
    property real to: 2.0
    property real stepSize: 0.1
    property real value: 0.2

    function getFrom() {
        return Math.min(rootItem.from, rootItem.to)
    }

    function getTo() {
        return Math.max(rootItem.from, rootItem.to)
    }

    SpinBox {
        id: cusSpinBox
        anchors.fill: parent

        editable: true
        leftPadding: 4
        rightPadding: 4
        topPadding: 4
        bottomPadding: 4

        validator: DoubleValidator {
            bottom: rootItem.getFrom()
            top: rootItem.getTo()
            decimals: rootItem.decimals
        }

        textFromValue: function(value, locate) {
            return Number(value).toLocaleString(locale, 'f', rootItem.decimals)
        }

        valueFromText: function(text, locale) {
            let tmpValue = Number.fromLocaleString(locale, text)
            console.log("valueFromText : " + text + " => " + tmpValue+" from: "+getFrom()+" to: "+getTo())

            if (tmpValue > getTo()) {
                tmpValue = getTo()
            }
            if (tmpValue < getFrom()) {
                tmpValue = getFrom()
            }
            let realValue = tmpValue.toFixed(decimals)
            rootItem.value = realValue
            console.log("2 realValue : " + realValue)
            return realValue
        }

        contentItem: STextInput {
            id: input
            color: "blue"
            width: cusSpinBox.width - cusSpinBox.up.indicator.width - cusSpinBox.leftPadding - cusSpinBox.rightPadding
            horizontalAlignment: Qt.AlignLeft
            verticalAlignment: Qt.AlignVCenter
            validator: cusSpinBox.validator
            text: cusSpinBox.textFromValue(rootItem.value, cusSpinBox.locale)
            readOnly: !cusSpinBox.editable
            selectByMouse: true
            inputMethodHints: Qt.ImhFormattedNumbersOnly
        }

        up.indicator: Image {
            x: cusSpinBox.width - width - cusSpinBox.rightPadding
            y: cusSpinBox.topPadding
            width: 18
            height: (cusSpinBox.height - cusSpinBox.topPadding - cusSpinBox.bottomPadding)/2 - 2
            source: JsConfig.imgPathPrefix() + "spinbox_up.png"
        }

        down.indicator: Image {
            x: cusSpinBox.width - width - cusSpinBox.rightPadding
            y: cusSpinBox.height - height - cusSpinBox.bottomPadding
            width: 18
            height: (cusSpinBox.height - cusSpinBox.topPadding - cusSpinBox.bottomPadding)/2 - 2
            source: JsConfig.imgPathPrefix() + "spinbox_down.png"
        }

        MouseArea {
            id: downArea
            hoverEnabled: true
            width : 18
            height :parent.height / 2
            anchors.right: parent.right
            anchors.top: parent.top
            cursorShape: Qt.PointingHandCursor
            onClicked: {
                cusSpinBox.increase()
            }
        }

        MouseArea {
            id : upArea
            hoverEnabled: true
            width : 18
            height : parent.height / 2
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            cursorShape: Qt.PointingHandCursor

            onClicked: {
                cusSpinBox.decrease()
            }
        }

        function increase() {
            let curRealValue = rootItem.value + rootItem.stepSize
            console.log(" 1 increase last value: "+rootItem.value+" curRealValue: "+
                        curRealValue.toFixed(decimals))
            rootItem.value = Math.min(curRealValue.toFixed(decimals), getTo())
        }

        function decrease() {
            let curRealValue = rootItem.value - rootItem.stepSize
            console.log(" 1 decrease last value: "+rootItem.value+" curRealValue: "+
                        curRealValue.toFixed(decimals))
            rootItem.value = Math.max(curRealValue.toFixed(decimals), getFrom())
        }
    }
}

微信公众号搜索:“上官宏竹”,关注并留言咨询,可接各类需求。


更多资讯、知识,微信公众号搜索:“上官宏竹”。
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值