PyQt5中如何为可调整大小的QTableView单元格设置可拉伸QLinearGradient背景?
解决QTableView单元格垂直渐变背景异常问题
问题现象
给QTableView第三列所有单元格添加垂直渐变背景时,出现以下异常:
- 仅第一行单元格渐变显示正常,其余行显示纯色
- 调整第二行高度后,该单元格渐变未按单元格边界比例拉伸
- 调整第一行高度后,第一行渐变恢复正常,但第二行渐变再次丢失
原因分析
原代码在模型初始化时创建了全局的渐变和画笔实例,使用QGradient.ObjectMode时,渐变的坐标会与第一次使用它的单元格(第一行)绑定。后续单元格复用该画笔时,渐变坐标不会重新适配新的单元格边界,导致显示异常。
解决方案
不要提前创建全局渐变画笔,而是在data()方法处理BackgroundRole时,为每个目标单元格单独创建渐变和画笔,确保渐变适配当前单元格的边界:
- 当触发
Qt.BackgroundRole且为目标列时,临时生成QLinearGradient - 设置渐变起始点为
(0, 0),结束点为(0, 1),并使用QGradient.ObjectBoundingMode(该模式会让渐变基于单元格边界自动拉伸) - 为当前渐变创建画笔并返回
修改后的完整代码
import sys from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import (Qt, QPointF) from PyQt5.QtGui import (QColor, QGradient, QLinearGradient, QBrush) class TableModel(QtCore.QAbstractTableModel): def __init__(self, data): super(TableModel, self).__init__() self._data = data self.bg_col1 = QColor("#A3A3FF") self.bg_col2 = QColor("#FFFFA3") def data(self, index, role): if role == Qt.DisplayRole: return self._data[index.row()][index.column()] if role == Qt.BackgroundRole: if index.column() == 2: # 为每个单元格单独创建渐变 bg_grad = QLinearGradient(QPointF(0.0, 0.0), QPointF(0.0, 1.0)) bg_grad.setCoordinateMode(QGradient.ObjectBoundingMode) bg_grad.setSpread(QGradient.PadSpread) bg_grad.setColorAt(0.0, self.bg_col1) bg_grad.setColorAt(1.0, self.bg_col2) return QBrush(bg_grad) def rowCount(self, index): return len(self._data) def columnCount(self, index): return len(self._data[0]) class MainWindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.table = QtWidgets.QTableView() data = [ [4, 9, 2], [1, 0, 0], [3, 5, 0], [3, 3, 2], [7, 8, 9], ] self.model = TableModel(data) self.table.setModel(self.model) self.setCentralWidget(self.table) app=QtWidgets.QApplication(sys.argv) window=MainWindow() window.show() app.exec_()
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

