QML 文本始终显示小数位

Posted

技术标签:

【中文标题】QML 文本始终显示小数位【英文标题】:QML text always display decimal places 【发布时间】:2021-07-19 15:50:39 【问题描述】:

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

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

如果可能,我希望尽可能避免使用复杂的 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())

【问题讨论】:

【参考方案1】:

问题在于,当您执行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__ 中的连接;

【讨论】:

谢谢你,完美! toFixed() 可以解决问题。并感谢您指出我的代码中的其他问题。!

以上是关于QML 文本始终显示小数位的主要内容,如果未能解决你的问题,请参考以下文章

如何始终在 R Shiny 的 DataTables 中显示 3 位小数? [关闭]

如何确保小数始终显示为 xxxx.xxxx 正负?

QML 在一行中显示多个文本

HTML5 数字输入 - 始终显示 2 位小数

如何使用 BigDecimal 显示始终有 2 个小数点的数字?

Android:BigDecimal 始终显示最多 2 位小数