PyQt中QStyledItemDelegate绘制复选框时穿透显示问题求助
问题分析与解决
问题根源在于自定义paint方法未正确处理控件背景绘制,导致列调整后之前的复选框绘制内容未被覆盖,出现穿透显示的情况;同时绘制时未严格限定在当前列的可视区域内。
修复后的代码
import sys from PyQt5 import QtCore, QtWidgets class CustomTreeWidgetDelegate(QtWidgets.QStyledItemDelegate): def __init__(self, parent=None) -> None: super().__init__(parent) def paint(self, painter, option, index): options = QtWidgets.QStyleOptionViewItem(option) self.initStyleOption(options, index) if options.widget: style = option.widget.style() else: style = QtWidgets.QApplication.style() # 先绘制item背景,清除原有残留内容 style.drawPrimitive(QtWidgets.QStyle.PE_PanelItemViewItem, options, painter, options.widget) # 仅在第0列绘制复选框 if index.column() == 0: item_options = QtWidgets.QStyleOptionButton() item_options.initFrom(options.widget) item_options.state = (QtWidgets.QStyle.State_On | QtWidgets.QStyle.State_Enabled) if options.checkState == QtCore.Qt.Checked else (QtWidgets.QStyle.State_Off | QtWidgets.QStyle.State_Enabled) item_options.rect = style.subElementRect(QtWidgets.QStyle.SE_ViewItemCheckIndicator, options) # 裁剪绘制区域,确保只在当前item范围内绘制 with painter.clipped(options.rect): QtWidgets.QApplication.style().drawControl(QtWidgets.QStyle.CE_CheckBox, item_options, painter) # 绘制文本 text = index.data(QtCore.Qt.DisplayRole) if text: rect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options) elided_text = options.fontMetrics.elidedText(text, QtCore.Qt.ElideRight, rect.width()) painter.drawText(rect, QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter, elided_text) if __name__ == "__main__": class MyTree(QtWidgets.QTreeWidget): def __init__(self): super().__init__() self.setItemDelegate(CustomTreeWidgetDelegate()) head = self.headerItem() head.setText(0, "Name") head.setText(1, "Age") parent = QtWidgets.QTreeWidgetItem(self) parent.setCheckState(0, QtCore.Qt.Unchecked) parent.setText(0, "Jack Smith") parent.setText(1, "30") child = QtWidgets.QTreeWidgetItem(parent) child.setCheckState(0, QtCore.Qt.Checked) child.setText(0, "Jane Smith") child.setText(1, "10") self.expandAll() App = QtWidgets.QApplication(sys.argv) myTree = MyTree() myTree.show() sys.exit(App.exec())
关键修复点
- 背景清除:添加
style.drawPrimitive(QtWidgets.QStyle.PE_PanelItemViewItem, ...),每次绘制前先填充item背景,覆盖之前的残留绘制内容。 - 区域裁剪:使用
painter.clipped(options.rect)包裹复选框绘制逻辑,确保所有绘制操作严格限定在当前item的可视范围内,避免跨列穿透。 - 逻辑简化:优化复选框状态判断逻辑,提升代码可读性。
内容的提问来源于stack exchange,提问作者LozzerJP
相关产品推荐
相关产品推荐

