需求场景
打算用python开发一款自用的工具箱,目前预设密码本和个人词典功能。因为个人的前端能力有限,所以放弃了基于flask的BS架构,转投pyqt5。但整个过程仍然遇到不少坑。
这篇文章旨在分享一个pyqt5 TableView控件清空数据的解决方案,同时也向广大网友寻求更优的解法。
如上图所示,最初的效果明显有问题:预期的效果是每次查询只显示当前条件下的查询结果,但实际却是将查询结果覆盖到了首行。
因此需要解决的问题就是如何在查询前先清空TableView控件中原有的数据。
寻求方案
网上转了一圈,提供的解决方案无外乎就是从model下手(答案大同小异,有的甚至文案都一模一样...╮(╯▽╰)╭)。
我使用的是QStandardItemModel,因此就有了QStandardItemModel().clear()和QStandardItemModel().removeRows(row,count)两种方法。两种方法的效果大致相同,不过clear()会连表头一起清理掉(这倒是可以在清理后再设置一次)。实际效果如下:
这个结果……多少有点一言难尽。这两个方法都会破坏TableView的结构,极其不美观,并且实际上也没有真正实现清空数据的效果:如果先查出数量较多的记录,再查出数量较少的记录,则新记录还是覆盖到了首行。
曲线救国
搜索良久也没有找到好方法,看来从一整行的角度是没戏了。忽然想到自己在填充数据时的做法:也不是一整行直接插入,而是迭代每一个单元格。那么清空数据是否也可以这么做呢?
于是就有了以下的野路子:
# 查询前先清理上一次的查询结果
for i in range(10):
for j in range(get_column_info()['main_col_count']):
clear_item = QStandardItem('')
self.data_model.setItem(i, j, clear_item)
查询前,先手动插入一些“数据”,这些空字符串将填充所有可见单元格,从视觉效果上实现了“清空数据”。
总结
方法缺陷
- 自我感觉这也不是一种好的解决方案,毕竟只是视觉上的欺骗,所幸本来也不打算开放TableView的编辑功能,这样可以晚一点露馅,但保不齐会造成其他未知的问题;
- 听说它儿子QTableWidget家里有不少现成的宝贝可以直接实现这种功能(clear()、clearContents()...)不知道有没有办法可以“借鉴”一下;
其他问题
除这个问题外,目前为止还遇到了其他坑,包括上述的显示数据只能一个个单元格插入而不是一整行(毕竟sqlalchemy查询出来的结果是一个list嵌套了dict)。
此外,还有一个更让人头疼的问题:代码分离。一开始图省事,想用uic.loadUi()的方法省去转换的步骤。但随着开发工作的推进,发现了越来越多的问题,譬如代码补全以及各种引用。最后迫使我放弃这种方法的原因是我打算在app里嵌入网页,但QT Designer没有现成的控件,使用代码手动构建又没找到好方法,只得乖乖转换UI文件。
但即使这样,依然存在代码分离的问题:我新建了一个类继承了UI转换出来的类,这个类我打算只用作菜单页切换,而其他具体的功能页面还是希望能和这个类分开来。目前尝试下来没有生效,后续看看有没有好的解决方案,否则所有功能页的代码都放到一个文件里,想想都觉得头大。