PySide6中QPainter.drawText参数匹配却报错的问题排查
问题分析与解决方案
这不是PySide6的bug,你的代码存在两处关键疏漏:
核心问题
- 未判断index有效性:QAbstractItemDelegate的
paint方法会在视图绘制空白区域等场景下收到无效的index,此时你的Model返回None,而QPainter.drawText要求text为字符串类型,PySide6将None转为空字符串后,结合宽度为0的无效绘制矩形触发了参数校验错误。 - 多余的drawText参数:你使用的
drawText重载中,第四个参数是可选的(用于接收文本实际绘制的边界矩形),无需主动传入重复的矩形。
修复代码
修改Delegate类的paint方法,添加有效性判断并简化参数:
from PySide6 import QtWidgets as qtw from PySide6 import QtGui as qtg from PySide6 import QtCore as qtc class Delegate(qtw.QAbstractItemDelegate): def paint(self, painter, option, index): # 优先判断索引是否有效,无效直接返回 if not index.isValid(): return text = index.model().data(index, qtc.Qt.ItemDataRole.DisplayRole) # 兜底处理,确保text为字符串类型 text = text or "" text_rect = qtc.QRect( option.rect.left(), option.rect.top(), option.rect.width(), 200 ) # 移除多余的第四个参数,若需获取绘制边界可传入空QRect painter.drawText(text_rect, 0, text) def sizeHint(self, option, index): return qtc.QSize(200, 200) # 以下Model和MainWindow代码保持不变 class Model(qtc.QAbstractListModel): def __init__(self) -> None: super().__init__() self._texts = ["text" for _ in range(10)] def rowCount(self, _) -> int: return 10 def data(self, index, role): if not index.isValid(): return None if role == qtc.Qt.ItemDataRole.DisplayRole: return self._texts[index.row()] return None class MainWindow(qtw.QMainWindow): def __init__(self): super().__init__() delegate = Delegate(self) self._model = Model() self._view = qtw.QListView(self) self._view.setModel(self._model) self._view.setItemDelegate(delegate) self.setCentralWidget(self._view) self.show() app = qtw.QApplication() mw = MainWindow() app.exec()
关键说明
- 索引有效性检查:这是自定义代理的标准规范,必须在
paint和sizeHint方法开头执行,避免处理无效索引导致的各种异常。 - 文本兜底处理:即使索引有效,也建议通过
text = text or ""确保参数为字符串,防止Model返回非预期类型。 - drawText参数理解:第四个参数是输出型参数,用于获取文本实际绘制的边界,不需要主动传入相同的矩形;如果需要使用该边界,可以传入一个空的
QRect对象。
内容的提问来源于stack exchange,提问作者オパラ
相关产品推荐
相关产品推荐

