Issue
I have some QML below where I want to always make sure that values up to the hundreth decimal place is always displayed. Currently, when you click on the big red button the number at the top will go up by 1. If the button is pressed and held, there is a timer that will help repeatedly increment the number while the button is held.
I am working with a float data type, and every time there is some sort of increment called, the trailing 0s will disappear. However, I need those 0s to be displayed. So I tried to insert some Javascript into the onClicked and onPressAndHold signals, but the line I have commented out displayVal.text = result
will cause the numbers to stop incrementing. Is my logic faulty, or is there a better way to add trailing 0s? I might as well also mention that just appending ".00" to the end of everything would not work because in the future, I will be dealing with decimal numbers that aren't whole, like 10.20 or 11.89. I am not too familiar with Javascript either so my current code snippet to try to add 0's came from another forum post. I know it partially works at least because of the print statement.
If possible, I would like to avoid as much complex Javascript as possible; complex as in needing functions or something. If this could even be handled in the Python code that would be even better.
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())
Solution
The problem is that when you do displayVal.text = result
you stop the ability to automatically update the displayed text from the model. The result is that, while the model is updated, the display text is not, as you set a static value for that.
The solution is to use toFixed
directly in the text
definition:
Text {
id: displayVal
text: model.display.toFixed(2)
font.pixelSize: 30
}
And set the value of the item as a number, not a string:
item.setData(10., DisplayRole)
This obviously means that you must remove all the computation you're trying to achieve after incrementOnce
and startIncrement
, since it's unnecessary any more.
Note that:
- you shouldn't overwrite the existing
display
role, and you should probably use another name if absolutely necessary; in reality, you can avoid setting the role names and use the standardQt.DisplayRole
to set the number (again, not as a string); - connecting the timer in the
start_increment
function is an error, as it will result in callingincrement
everytime you connect it: if you press the button twice, the increment will be done twice, if you press it three times, it will increment by 3, etc. Move the connection in the__init__
;
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.