为什么这个角色总是sizeHintRole?
Why is this role always sizeHintRole?
我一直在为 PySide2
编写 C++
示例代码。
我一遍又一遍地回顾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, 0)
layout.addWidget(self.lineEdit, 0, 1)
layout.addWidget(self.view, 1, 0, 1, 2)
layout.addWidget(self.logViewer, 2, 0, 1, 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_())
问题出在data()
的最后return,不应该是return0.
当 returning 0 时,视图或其委托尝试将值转换为适合该角色的类型,并且由于视图请求的第一个角色是大小提示(并且无法将您的 returned "0" 转换为有效的尺寸提示),结果是它不会请求任何其他数据:由于尺寸无效,该项目被认为是隐藏的,因此无需询问其他角色。
只需删除 data()
末尾的 return 0
,因为隐含的 return
就足够了。
PS:您使用的 self.emit
语法被认为已过时,请将其更改为 self.numberPopulated.emit(itemsToFetch)
;此外,只有一个签名的信号不需要显式重载,因此您可以从 textChanged
中删除 ["QString"]
并从 numberPopulated
.
中删除 [int]
我还建议您始终在函数之间至少留一个空行,因为它使您的代码更具可读性。
我的回答会稍微扩展的解释。
QVariant 是一种 Qt/C++ 对象,允许处理各种类型的数据,但在 python 中,考虑到语言的动态类型,不再需要该对象类型,因此它是不必将其导出到 python(尽管 PyQt5 可以)。 QVariant() 构建一个无效的 QVariant,python 等价于 None 因此 return QVariant()
可以转换为 return None
或简单地 return
.
同样可以反过来,因为当返回 0
时,它在 C++ 中被转换为 0
,然后被转换为 QVariant(0)
,这与 [=16] 具有不同的含义=],因为第一个存储数字 0 而第二个不存储任何内容,因为它是无效的 QVariant。
我一直在为 PySide2
编写 C++
示例代码。
我一遍又一遍地回顾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, 0)
layout.addWidget(self.lineEdit, 0, 1)
layout.addWidget(self.view, 1, 0, 1, 2)
layout.addWidget(self.logViewer, 2, 0, 1, 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_())
问题出在data()
的最后return,不应该是return0.
当 returning 0 时,视图或其委托尝试将值转换为适合该角色的类型,并且由于视图请求的第一个角色是大小提示(并且无法将您的 returned "0" 转换为有效的尺寸提示),结果是它不会请求任何其他数据:由于尺寸无效,该项目被认为是隐藏的,因此无需询问其他角色。
只需删除 data()
末尾的 return 0
,因为隐含的 return
就足够了。
PS:您使用的 self.emit
语法被认为已过时,请将其更改为 self.numberPopulated.emit(itemsToFetch)
;此外,只有一个签名的信号不需要显式重载,因此您可以从 textChanged
中删除 ["QString"]
并从 numberPopulated
.
中删除 [int]
我还建议您始终在函数之间至少留一个空行,因为它使您的代码更具可读性。
我的回答会稍微扩展
QVariant 是一种 Qt/C++ 对象,允许处理各种类型的数据,但在 python 中,考虑到语言的动态类型,不再需要该对象类型,因此它是不必将其导出到 python(尽管 PyQt5 可以)。 QVariant() 构建一个无效的 QVariant,python 等价于 None 因此 return QVariant()
可以转换为 return None
或简单地 return
.
同样可以反过来,因为当返回 0
时,它在 C++ 中被转换为 0
,然后被转换为 QVariant(0)
,这与 [=16] 具有不同的含义=],因为第一个存储数字 0 而第二个不存储任何内容,因为它是无效的 QVariant。