我正在编写一个应用程序,它使用自定义QWidget代替PyQt中的常规listitems或委托。我已经按照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):
pass
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()
答案 0 :(得分:2)
您可以使用代理模型来避免加载所有小部件。代理模型可以使用视口和窗口小部件的高度来计算行数。他可以使用滚动条值计算项目的索引。
这是一个不稳定的解决方案,但它应该有效。
如果使用以下命令修改data()方法:
button = QtGui.QPushButton("This is item #%s" % index.row())
self.list.setIndexWidget(index, button)
button.setVisible(False)
这些项目在他们的位置被移动之前不会显示(它对我有用)。
答案 1 :(得分:1)
QTableView
仅向模型请求其视口中的项目的数据,因此数据的大小不会真正影响速度。由于您已经将QAbstractListModel
子类化,因此您可以重新实现它,以便在初始化时仅返回一小组行,如果记录总数没有,则修改其canFetchMore
方法以返回True
已经显示出来虽然,根据您的数据大小,您可能需要考虑创建数据库并使用QSqlQueryModel
或QSqlTableModel
,但它们都会以256个为一组进行延迟加载。
要获得更顺畅的项目加载,您可以连接到valueChanged
的QTableView.verticalScrollBar()
信号,并根据value
和maximum
之间的差异,具有以下内容:
while xCondition:
if self.model.canFetchMore():
self.model.fetchMore()
使用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)
painter.save()
painter.translate(option.rect.x(), option.rect.y())
pushButton.render(painter)
painter.restore()
并设置:
myView.setItemDelegateForColumn(columnNumber, myItemDelegate)