QML 文本始终显示小数位

QML text always display decimal places

我在下面有一些 QML,我希望始终确保始终显示小数点后百分之一的值。目前,当你点击红色的大按钮时,顶部的数字会增加 1。如果按住按钮,有一个计时器可以帮助在按住按钮时重复递增数字。

我正在使用浮点数据类型,每次调用某种增量时,尾随的 0 都会消失。但是,我需要显示那些 0。所以我尝试在 onClicked 和 onPressAndHold 信号中插入一些 Javascript,但是我注释掉的行 displayVal.text = result 会导致数字停止递增。是我的逻辑有问题,还是有更好的方法来添加尾随 0?我不妨还提到,仅在所有内容的末尾附加“.00”是行不通的,因为将来我将处理不完整的十进制数字,例如 10.20 或 11.89。我也不太熟悉 Javascript,所以我当前尝试添加 0 的代码片段来自另一个论坛 post。我知道它部分有效,至少是因为打印语句。

如果可能的话,我想尽可能避免复杂Javascript;复杂到需要功能什么的。如果这甚至可以在 Python 代码中处理,那就更好了。

main.qml:

import QtQuick 2.14
import QtQuick.Layouts 1.12
import QtQuick.Controls.Material 2.15

Item {
    visible: true
    width: 600; height: 400
    
    id: itemView
    
    signal startIncrement()
    signal stopIncrement()
    
    signal incrementOnce()
    
    ColumnLayout{
        Repeater{
        model: modelManager.model
        
            ColumnLayout{
                Text {
                    id: displayVal
                    text: model.display
                    font.pixelSize: 30
                }
        
                Rectangle{
                    id: incrementButton
                    color: "red"
                    width: 250
                    height: 100
                    
                    MouseArea {
                        anchors.fill: parent
                        onClicked: {
                            incrementOnce()
                            var num = parseFloat(displayVal.text)
                            var result = num.toFixed(Math.max(2, (num.toString().split('.')[1] || []).length));
//                          displayVal.text = result
                            console.log("OnClick Formatted #: " + result + " DisplayVal: " + displayVal.text)
                        }
                        onPressAndHold:{
                            startIncrement()
                            var num = parseFloat(displayVal.text)
                            var result = num.toFixed(Math.max(2, (num.toString().split('.')[1] || []).length));
        //                  displayVal.text = result
                            console.log("Started increment")
                        }
                        onReleased:{
                            stopIncrement()
                            console.log("Stopped increment")
                        }
                    }
                }
            }
        }
    }
}

main.py:

import os
import sys

from pathlib import Path
sys.path.append(os.path.join(os.path.dirname(sys.path[0]), ".."))

from PySide6.QtCore import QUrl, Qt, QCoreApplication, QTimer, QObject, Property
from PySide6.QtGui import QGuiApplication, QStandardItemModel, QStandardItem
from PySide6.QtQuick import QQuickView

CURRENT_DIRECTORY = Path(__file__).resolve().parent

DisplayRole = Qt.UserRole
class ModelManager(QObject):
    def __init__(self):
        super().__init__()
        self._model = QStandardItemModel()
        self._model.setItemRoleNames({DisplayRole: b"display"})
        item = QStandardItem()
        item.setData("10.00", DisplayRole)
        self._model.appendRow(item)
        self.timer = QTimer()
        self.timer.setInterval(100)
        
    @Property(QObject, constant=True)
    def model(self):
        return self._model
    
    def start_increment(self):
        self.timer.timeout.connect(self.increment)
        self.timer.start()
    
    def increment(self):
        presentVal = float(self._model.item(0).data(DisplayRole)) +1.0
        self._model.item(0).setData(presentVal, DisplayRole)
        print(presentVal)
        
    def stop_increment(self):
        if self.timer.isActive():
            self.timer.stop()        

if __name__ == '__main__':
    app = QGuiApplication(sys.argv)
    view = QQuickView()
    
    view.setResizeMode(QQuickView.SizeRootObjectToView)

    url = QUrl.fromLocalFile(os.fspath(CURRENT_DIRECTORY / "main.qml"))

    def handle_status_changed(status):
        if status == QQuickView.Error:
            QCoreApplication.exit(-1)
    
    modelManager = ModelManager()
    view.rootContext().setContextProperty("modelManager", modelManager)
    
    view.statusChanged.connect(handle_status_changed, Qt.ConnectionType.QueuedConnection)
    view.setSource(url)
     
    root = view.rootObject()
    root.startIncrement.connect(modelManager.start_increment)
    root.stopIncrement.connect(modelManager.stop_increment)
    root.incrementOnce.connect(modelManager.increment)
    
    view.show()
    
    sys.exit(app.exec())

问题是,当您执行 displayVal.text = result 时,您会停止自动更新模型中显示的文本的能力。结果是,当模型更新时,显示文本不会,因为您为此设置了一个静态值。

解决方法是在text定义中直接使用toFixed

    Text {
        id: displayVal
        text: model.display.toFixed(2)
        font.pixelSize: 30
    }

将项目的值设置为数字,而不是字符串:

    item.setData(10., DisplayRole)

这显然意味着您必须删除在 incrementOncestartIncrement 之后尝试实现的所有计算,因为它不再是不必要的。

注意:

  • 您不应该覆盖现有的 display 角色,如果绝对必要,您应该使用另一个名称;实际上,您可以避免设置角色名称并使用标准 Qt.DisplayRole 设置数字(同样,不是字符串);
  • start_increment函数中连接定时器是一个错误,因为它会导致每次连接时调用increment:如果你按两次按钮,就会增加两次,如果按三下,它将递增 3,依此类推。移动 __init__;
  • 中的连接