为什么这个角色总是sizeHintRole?

问题描述

我一直在为 C++ 制作 pyside2 示例代码

我一遍又一遍地复习fetchMore example

这个转换的错误点在哪里?

最大的问题在于数据方法

角色总是SizeHintRole

为什么?

这是代码

# -*- coding: utf-8 -*-
import sys,os,pyside2
from pyside2 import QtCore,QtWidgets,QtGui


dirname  =  os.path.dirname(pyside2.__file__)
plugin_path  =  os.path.join(dirname,'plugins','platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH']  =  plugin_path

class Window(QtWidgets.QWidget):
    def __init__(self,parent=None):
        super(Window,self).__init__(parent)
        self.model = FileListModel()
        #6.0
#        self.model.setDirPath(QtCore.QLibraryInfo.path(QtCore.QLibraryInfo.PrefixPath))
        self.model.setDirPath(QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.PrefixPath))
        self.label = QtWidgets.QLabel("&Directory:")
        self.lineEdit = QtWidgets.QLineEdit()
        self.label.setBuddy(self.lineEdit)
        self.view = QtWidgets.QListView()
        self.view.setModel(self.model)
        self.logViewer = QtWidgets.QTextbrowser(self)
        self.logViewer.setSizePolicy(QtWidgets.QSizePolicy.Preferred,QtWidgets.QSizePolicy.Preferred)
        self.lineEdit.textChanged["QString"].connect(self.model.setDirPath)
        self.lineEdit.textChanged["QString"].connect(self.logViewer.clear)
        self.model.numberPopulated[int].connect(self.updateLog)
        layout = QtWidgets.qgridLayout()
        layout.addWidget(self.label,0)
        layout.addWidget(self.lineEdit,1)
        layout.addWidget(self.view,1,2)
        layout.addWidget(self.logViewer,2,2)
        self.setLayout(layout)
        self.setwindowTitle("Fetch More Example")
    def updateLog(self,number):
        self.logViewer.append("{0} items added.".format(number))
        
class FileListModel(QtCore.QAbstractListModel):
    numberPopulated = QtCore.Signal(int)
    def __init__(self,parent=None):
        super(FileListModel,self).__init__(parent)
        self.fileCount = 0
        self.fileList = []
    def rowCount(self,parent=QtCore.QModelIndex()):
        return 0 if parent.isValid() else self.fileCount
    def data(self,index,role=QtCore.Qt.displayRole):     
        if not index.isValid():
            return 0       
        if (index.row() >= len(self.fileList) or index.row() < 0):
            return 0      
        #Why is the role only SizeHintRole?
        if role == QtCore.Qt.displayRole:
            return self.fileList[index.row()]
        elif role == QtCore.Qt.BackgroundRole:
            batch = (index.row() / 100) % 2
            if batch == 0:
                return QtWidgets.QApplication.palette().base()
            else:
                return QtWidgets.QApplication.palette().alternateBase()
        return 0
    def canFetchMore(self,parent):
        if parent.isValid():
            return False
        return self.fileCount < len(self.fileList)
    def fetchMore(self,parent):
        if parent.isValid():
            return
        remainder = len(self.fileList) - self.fileCount
        itemsToFetch = min(100,remainder)
  
        if itemsToFetch <= 0:
            return
        self.beginInsertRows(QtCore.QModelIndex(),self.fileCount,self.fileCount + itemsToFetch - 1)
        
        self.fileCount += itemsToFetch
        self.endInsertRows()
        self.emit(QtCore.SIGNAL("numberPopulated(int)"),itemsToFetch)
    def setDirPath(self,path):
        dir_ = QtCore.QDir(path)
        self.beginResetModel()
        self.fileList = dir_.entryList()        
        self.fileCount = 0
        self.endResetModel()        
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv) if QtWidgets.QApplication.instance() is None else QtWidgets.QApplication.instance()
    mainWin = Window()
    mainWin.show()
    sys.exit(app.exec_())

解决方法

我的回答会稍微扩展musicamante's answer的解释。

QVariant 是一种 Qt/C++ 对象,它允许处理各种类型的数据,但在 Python 中,鉴于语言的动态类型,不再需要该对象类型,因此没有必要将其导出到 Python(虽然 PyQt5做)。 QVariant() 构建了一个无效的 QVariant,它的 Python 等效项是 None,因此 return QVariant() 可以转换为 return None 或简单地 return

同样可以颠倒,因为当返回 0 时,它在 C++ 中被转换为 0,然后它被转换为 QVariant(0),这与 QVariant() 的含义不同,因为第一个存储数字 0,第二个不存储任何内容,因为它是无效的 QVariant。

,

问题出在 data() 的最后一个返回,不应返回 0。

当返回 0 时,视图或其委托尝试将值转换为适合该角色的类型,并且由于视图请求的第一个角色是大小提示(并且无法转换您返回的“ 0" 到一个有效的大小提示),结果是它不会请求任何其他数据:由于大小无效,项目被认为是隐藏的,因此不需要请求其他角色。

只需删除 return 0 末尾的 data(),因为隐式 return 就足够了。

PS:您使用的 self.emit 语法已过时,请将其更改为 self.numberPopulated.emit(itemsToFetch);此外,只有一个签名的信号不需要显式重载,因此您可以从 ["QString"] 中删除 textChanged,从 [int] 中删除 numberPopulated
我还建议您始终在函数之间至少留一个空行,因为它会使您的代码更具可读性。