4

PyQt の通常のリストアイテムまたはデリゲートの代わりにカスタム QWidget を使用するアプリケーションを作成しています。QListView の QWidgetDelegate の paint() メソッドで QWidget をレンダーする の回答に従って、カスタム ウィジェットで QTableModel を実装しました。結果のサンプル コードは、この質問の最後にあります。実装には、解決方法がわからない問題がいくつかあります。

  1. 表示されていないアイテムのアンロード。何千ものエントリを持つリスト用にアプリケーションを構築する予定ですが、それほど多くのウィジェットをメモリに保持することはできません。
  2. まだ表示されていないアイテムをロードするか、少なくとも非同期でロードします。ウィジェットのレンダリングには少し時間がかかります。また、以下のコード例では、リストをスクロールするときに明らかな遅延が発生しています。
  3. 以下の実装でリストをスクロールすると、ロード時に新しくロードされた各ボタンが 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()
4

2 に答える 2

2

プロキシ モデルを使用して、すべてのウィジェットの読み込みを回避できます。プロキシ モデルは、ビューポートとウィジェットの高さを使用して行数を計算できます。彼は、スクロールバーの値を使用して項目のインデックスを計算できます。

これは不安定なソリューションですが、うまくいくはずです。

data() メソッドを次のように変更した場合:

button = QtGui.QPushButton("This is item #%s" % index.row())
self.list.setIndexWidget(index, button)
button.setVisible(False)

アイテムは、その位置に移動するまで表示されません (私にとってはうまくいきます)。

于 2013-03-21T13:20:52.037 に答える
1

QTableViewビューポート内のアイテムのモデルにデータを要求するだけなので、データのサイズは実際には速度に影響しません。すでにサブクラス化しているので、初期化時に小さな行セットのみを返すように再実装し、総レコード数が表示されていない場合に返すようにメソッドをQAbstractListModel変更できます。データのサイズによっては、データベースを作成し、代わりにorを使用することを検討することもできますが、どちらも 256 のグループで遅延読み込みを行います。canFetchMoreTrueQSqlQueryModelQSqlTableModel

アイテムのよりスムーズなロードを取得するには、 のvalueChanged信号に接続し、とQTableView.verticalScrollBar()の違いに応じて、次のようなものを使用できます。valuemaximum

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)
于 2013-03-22T18:11:44.067 に答える