Reputation: 209
I have got a QSqlTableModel with decimal numbers in one column. How can I format this column to have numbers with 4 decimal places (e.g.: 2,3 --> 2,3000; 4,567891 --> 4,5679). I am using pyqt5.
Edit:
I tried to subclass QSqlTableModel like this:
class AlignmentTable(QSqlTableModel):
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole and index.column() == 4:
value = '{:01.4f}'.format(self.data(index))
return value
But I get the error: RecursionError: maximum recursion depth exceeded in comparison
First I load the model like this:
def load_sitesizes(self):
self.mod_site_sizes = AlignmentTable(parent=None, db=dbtools.ProjectDB.use_project_db(self))
self.mod_site_sizes.setTable("vSiteSizes")
site_id = str(self.item_id)
self.mod_site_sizes.setFilter("SiteKey='"+site_id+"'")
self.mod_site_sizes.select()
self.mod_site_sizes.setEditStrategy(QSqlTableModel.OnFieldChange)
self.tblSiteSizes.setModel(self.mod_site_sizes)
and than your code in a subclass:
class AlignmentTable(QSqlTableModel):
def data(self, item, role):
if role == Qt.DisplayRole:
if item.column() == 4:
val = QSqlTableModel.data(self, item, Qt.DisplayRole)
if not isinstance(val, float):
val = float(val)
return '{:.4f}'.format(round(val, 4))
Upvotes: 2
Views: 3945
Reputation: 244311
You should not access the self.data(item)
function since you are calling the same function, you must access through the parent: QSqlTableModel.data(self, item, Qt.DisplayRole)
.
period:
def data(self, item, role):
if role == Qt.DisplayRole:
if item.column() == 4:
val = QSqlTableModel.data(self, item, Qt.DisplayRole)
if not isinstance(val, float):
val = float(val)
return '{:.4f}'.format(round(val, 4))
commas:
def data(self, item, role):
if role == Qt.DisplayRole:
if item.column() == 4:
number = round(float(QSqlTableModel.data(self, item, Qt.DisplayRole).replace(",", ".")),4)
return ('{:.4f}'.format(number)).replace(".", ",")
return QSqlTableModel.data(self, item, role)
According to what I observe in your database, the field of column 4 is of decimal type and the problem is that pyqt recognizes it as integer, the solution is simple, you must convert it to floating:
class CustomSqlModel(QSqlTableModel):
def __init__(self, parent=None):
QSqlTableModel.__init__(self, parent=parent)
self.setTable("SiteSizes")
self.setEditStrategy(QSqlTableModel.OnFieldChange)
self.select()
def data(self, item, role):
val = QSqlTableModel.data(self, item, role)
if role == Qt.DisplayRole:
if item.column() == 4:
try:
return '{:.4f}'.format(round(float(val), 4))
except ValueError:
pass
if role == Qt.EditRole:
if item.column() == 4:
try:
return float(val)
except ValueError:
pass
return val
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName("zzProjekt1.db")
model = CustomSqlModel()
view = QTableView()
view.resizeColumnsToContents()
view.setModel(model)
view.setWindowTitle("Custom Model")
view.show()
sys.exit(app.exec_())
Another additional thing is that when editing the default number can be edited 2 decimals, to change it to 4 decimals you can use the following class:
class NumberFormatDelegate(QItemDelegate):
def __init__(self, parent=None):
QItemDelegate.__init__(self, parent)
def createEditor(self, parent, option, index):
editor = QDoubleSpinBox(parent)
editor.setMaximum(10**10)
editor.setDecimals(4)
return editor
[...]
view.setItemDelegateForColumn(4, NumberFormatDelegate())
Note: Another thing I've noticed from your database is that vSiteSizes is not a Table, it's a View, and it's read-only, so you can not edit it.
Upvotes: 3