QTableView动态行高大QAbstractTableModel



我知道在stackoverflow上有很多关于如何设置QTableView的行高的问题。我再问一次,但我的问题不是"如何",至少不是那么简单。我在QAbstractTableModel衍生的自定义模型的数据方法中的Qt.SizeHintRole的帮助下成功设置行高-参见下面的代码。(也尝试了非常类似的例子,但借助QStyledItemDelegatesizeHint()方法-结果完全相同)

它工作得很好,当我有MODEL_ROW_COUNT大约100,如下面的例子。但是我的数据集有~3 -4万行。因此,这个简单的应用程序以MODEL_ROW_COUNT=35000为例启动大约30秒。
这个大延迟的原因是这行代码:
self.table_view.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
如果我注释这行,MODEL_ROW_COUNT=35000的一切都工作得很快。但是在这种情况下,data()方法没有被Qt.SizeHintRole调用,我不能操纵行高。

所以,我的问题是-如何设置行高度在每行的基础上与数千行数据集?下面的例子工作,但需要30秒开始与35000行(窗口后显示一切流畅)…

同时,如果我使用QSqlTableModel,它没有这个问题,我可以使用QStyledItemDelegatesizeHint(),没有大的问题。但是有太多的代表会造成混乱……我可以子类QStyledItemDelegate而不是QAbstractTableModel来实现我的自定义模型吗?(我不确定它是否会像每个源建议一样为自定义模型子类QAbstractTableModel工作…)或者我做错了什么,有比使用QHeaderView.ResizeToContents更好的方法吗?

注:我真的需要不同的高度。数据库中的一些行数据较少,我可能会在几个单元格中显示它们。但其他人有更多的数据,我需要额外的空间来显示它。所有行的高度相同意味着要么浪费空间(屏幕上有大量空白),要么缺乏某些数据行的基本细节。我使用内容CUSTOM_ROW_HEIGHT只是为了保持示例尽可能简单和易于再现-您可以使用任何数据库与任何大表(我想我可以重新创建它,即使没有DB…我会尽快)

from PySide2.QtWidgets import QApplication, QWidget, QVBoxLayout, QTableView, QHeaderView
from PySide2.QtSql import QSqlDatabase, QSqlQuery
from PySide2.QtCore import Qt, QAbstractTableModel, QSize

class MyWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.db = QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("/home/db.sqlite")
self.db.open()
self.table_model = MyModel(parent=self, db=self.db)
self.table_view = QTableView()
self.table_view.setModel(self.table_model)
# SizeHint is not triggered without this line but it causes delay
self.table_view.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
layout = QVBoxLayout(self)
layout.addWidget(self.table_view)
self.setLayout(layout)
class MyModel(QAbstractTableModel):
CUSTOM_ROW_HEIGHT = 300
MODEL_ROW_COUNT = 100
MODEL_COL_COUNT = 5
def __init__(self, parent, db):
QAbstractTableModel.__init__(self, parent)
self.query = QSqlQuery(db)
self.query.prepare("SELECT * FROM big_table")
self.query.exec_()
def rowCount(self, parent=None):
return self.MODEL_ROW_COUNT
def columnCount(self, parent=None):
return self.MODEL_COL_COUNT
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
if role == Qt.DisplayRole:
if self.query.seek(index.row()):
return str(self.query.value(index.column()))
if role == Qt.SizeHintRole:
return QSize(0, self.CUSTOM_ROW_HEIGHT)
return None

def main():
app = QApplication([])
win = MyWindow()
win.show()
app.exec_()
if __name__ == "__main__":
main()

好的,感谢@musicamante,我意识到我错过了canFetchMore()fetchMore()方法。因此,我在MyModel类中实现了动态大小属性和这些方法。这一点都不难,现在我有了比QSqlTableModel更好的性能和相同的视觉行为,直接控制可见缓冲区大小。以下是MyModel类的新代码:

class MyModel(QAbstractTableModel):
CUSTOM_ROW_HEIGHT = 300
MODEL_ROW_COUNT = 37000
MODEL_COL_COUNT = 5
PAGE_SIZE = 500
def __init__(self, parent, db):
QAbstractTableModel.__init__(self, parent)
self.query = QSqlQuery(db)
self.query.prepare("SELECT * FROM big_table")
self.query.exec_()
self._current_size = self.PAGE_SIZE
def rowCount(self, parent=None):
return self._current_size
def columnCount(self, parent=None):
return self.MODEL_COL_COUNT
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return None
if role == Qt.DisplayRole:
if self.query.seek(index.row()):
return str(self.query.value(index.column()))
if role == Qt.SizeHintRole:
return QSize(0, self.CUSTOM_ROW_HEIGHT)
return None
def canFetchMore(self, index):
return self._current_size < self.MODEL_ROW_COUNT
def fetchMore(self, index):
self.beginInsertRows(index, self._current_size, self._current_size + self.PAGE_SIZE - 1)
self._current_size += self.PAGE_SIZE
self.endInsertRows()

相关内容

  • 没有找到相关文章

最新更新