Python PyQt5的小坑

  1. QSqlTableModel删除错误行

QSqlTableModel使用filter/sort查询并删除行row时,TableView给出的index.row()和数据库中table不一致,导致删除错误行

解决办法:查询和删除时使用相同model实例。或者不同的实例使用相同的filter。

  1. Qt删除,插入,更新时 寻找数据库表table中行row的机制

Qt内部使用的是primaryKey对应的primaryValues(index.row())来删除,而primaryKey是在setTable的时候自动读取的。如果没有成功设置primaryKey,有可能会导致无法删除数据。

插入数据时,如果primaryKey在数据库是自动生成的,一般是integer,每次+1。从Qt插入record数据(相当于sql里说的row)的时候,默认也会自动生成一个值,这时就会插入错误。

The issue is caused by a discrepancy between the SQLite-generated PK and the QT-generated PK.

  • https://stackoverflow.com/questions/42319333/qsqlrecords-inserted-into-model-are-empty-blank-in-qtableview

解决办法,isGenerated要设置为False

record.setGenerated('tableid', False)

另外 Qt文档说了关于没有primary key的情况

QSqlRecord QSqlTableModel::primaryValues(int row) const
Returns a record containing the fields represented in the primary key set to the values at row. If no primary key is defined, the returned record will contain all fields.
This function was introduced in Qt 5.1.

  • https://doc.qt.io/qt-5/qsqltablemodel.html

bool QSqlTableModel::selectRow(int row)
Refreshes row in the model with values from the database table row matching on primary key values. Without a primary key, all column values must match. If no matching row is found, the model will show an empty row.
Returns true if successful; otherwise returns false.
This function was introduced in Qt 5.0.

  • https://doc.qt.io/qt-5/qsqltablemodel.html

Qt这个做法感觉不是很靠谱,不如读取数据库内部的RowNumber作为primaryKey,比如sqlite里的rowid。总之,QSql和其中的QSqlTableModel都不够灵活,不如自己写Model。

  1. Qt的data储存在哪?

明显不是想让人直接访问的。QAbstractItemModel中是在QPersistentModelIndexData的实例d中,通过index访问。QStandardItemModel中是在model.invisibleRootItem()里。具体再细节的位置不想研究了,自己写model最方便。

  1. QThread多线程的使用方法

由于QtConcurrent是name space,所以PyQt,PySide都没有QtConcurrent.run(),貌似以后也不会有。

曾经官方推荐用继承QThread重写 __init____del__run方法。后来有Qt内部核心大牛说这样用不对,推荐用QObject.moveToThread()方法。所以就用moveToThread吧。

model = MyModel()
thread = QtCore.QThread()
model.moveToThread(thread)
model.finished.connect(thread.quit)
thread.started.connect(model.func_to_run)
thread.finished.connect(func_to_run_after_thread_finished)
thread.start()

也可以写成一个函数把这段包起来,甚至写成一个装饰器。


不再更新,转投了PySide。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值