我正在编写一个应用程序,它使用自定义QWidget代替PyQt中的常规词条或委托。我遵循了 Render QWidget in paint() method of QWidgetDelegate for a QListView 中的答案--除其他外--用自定义小部件实现QTableModel。生成的示例代码位于此问题的底部。在实现方面存在一些问题,我不知道如何解决:
--
import sys from PyQt4 import QtGui, QtCore from PyQt4.QtCore import Qt class TestListModel(QtCore.QAbstractListModel): def __init__(self, parent=None): QtCore.QAbstractListModel.__init__(self, parent) self.list = parent def rowCount(self, index): return 1000 def data(self, index, role): if role == Qt.DisplayRole: if not self.list.indexWidget(index): button = QtGui.QPushButton("This is item #%s" % index.row()) self.list.setIndexWidget(index, button) return QtCore.QVariant() if role == Qt.SizeHintRole: return QtCore.QSize(100, 50) def columnCount(self, index): def main(): app = QtGui.QApplication(sys.argv) window = QtGui.QWidget() list = QtGui.QListView() model = TestListModel(list) list.setModel(model) list.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel) layout = QtGui.QVBoxLayout(window) layout.addWidget(list) window.setLayout(layout) window.show() sys.exit(app.exec_()) if __name__ == '__main__': main()
发布于 2013-03-21 13:20:52
您可以使用代理模型来避免加载所有小部件。代理模型可以用viewport和小部件的高度计算行计数。他可以用滚动条值计算项目的索引。
这是一个摇摇欲坠的解决方案,但应该有效。
如果使用以下方法修改data()方法:
button = QtGui.QPushButton("This is item #%s" % index.row()) self.list.setIndexWidget(index, button) button.setVisible(False)
这些项目将不会显示,直到他们被移动到他们的位置(它为我工作)。
发布于 2013-03-22 18:11:44
QTableView 只为其视口中的项向模型请求数据,因此数据的大小不会真正影响速度。因为您已经对 QAbstractListModel 进行了子类化,所以您可以重新实现它,在初始化时只返回一小部分行,并修改它的 canFetchMore 方法,以便在未显示记录总数时返回 True 。尽管在数据大小的情况下,您可能想考虑创建一个数据库,而不是使用 QSqlQueryModel 或 QSqlTableModel ,但它们都是在256个组中延迟加载的。
QTableView
QAbstractListModel
canFetchMore
True
QSqlQueryModel
QSqlTableModel
要获得更流畅的项目负载,您可以连接到 valueChanged 信号的 QTableView.verticalScrollBar() ,并且取决于它的 value 和 maximum 之间的区别,有如下所示:
valueChanged
QTableView.verticalScrollBar()
value
maximum
while xCondition: if self.model.canFetchMore(): self.model.fetchMore()
使用 setIndexWidget 会大大降低应用程序的速度。您可以使用 QItemDelegate 并自定义它的 paint 方法来显示按钮,如下所示:
setIndexWidget
QItemDelegate
paint
class MyItemDelegate(QtGui.QItemDelegate): def __init__(self, parent=None): super(MyItemDelegate, self).__init__(parent) def paint(self, painter, option, index): text = index.model().data(index, QtCore.Qt.DisplayRole).toString() pushButton = QtGui.QPushButton() pushButton.setText(text) pushButton.setGeometry(option.rect)