PyQt の通常のリストアイテムまたはデリゲートの代わりにカスタム QWidget を使用するアプリケーションを作成しています。QListView の QWidgetDelegate の paint() メソッドで QWidget をレンダーする の回答に従って、カスタム ウィジェットで QTableModel を実装しました。結果のサンプル コードは、この質問の最後にあります。実装には、解決方法がわからない問題がいくつかあります。
- 表示されていないアイテムのアンロード。何千ものエントリを持つリスト用にアプリケーションを構築する予定ですが、それほど多くのウィジェットをメモリに保持することはできません。
- まだ表示されていないアイテムをロードするか、少なくとも非同期でロードします。ウィジェットのレンダリングには少し時間がかかります。また、以下のコード例では、リストをスクロールするときに明らかな遅延が発生しています。
- 以下の実装でリストをスクロールすると、ロード時に新しくロードされた各ボタンが QListView の左上隅に一瞬表示されてから、所定の位置に跳ね返ります。どうすればそれを回避できますか?
--
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()