我正在用 Python 构建一个 Qt 表来显示一个大的 pandas DataFrame。该表使用自定义 PandasTableModel(QAbstractTableModel 的子类)连接到 DataFrame,我想有条件地突出显示单元格,例如,红色表示 False 值,绿色表示 True。
我找到了两种方法:
在模型中使用
data
方法:根据某些单元格的值返回特定的背景颜色。
class PandasTableModel(QtCore.QAbstractTableModel):
...
@override
def data(self, index, role):
if not index.isValid():
return None
value = self._dataframe.iloc[index.row(), index.column()]
if role == QtCore.Qt.ItemDataRole.DisplayRole:
return str(value)
elif role == QtCore.Qt.ItemDataRole.BackgroundRole:
if value == "True":
return QtGui.QColor(0, 255, 0, 100)
elif value == "False":
return QtGui.QColor(255, 0, 0, 100)
return None
使用自定义委托的
paint
方法:在委托的 paint
方法中设置单元格的背景颜色(来自 QItemDelegate
的子类):
class PandasItemDelegate(QtWidgets.QItemDelegate):
...
@override
def paint(self, painter, option, index):
super().paint(painter, option, index)
value = index.data(QtCore.Qt.ItemDataRole.DisplayRole)
if value in ["True", "False"]:
color = QtGui.QColor(0, 255, 0, 100) if value == "True" else QtGui.QColor(255, 0, 0, 100)
painter.fillRect(option.rect, color)
就内存和处理速度而言,哪种方法更有效,尤其是对于大型 DataFrame?
QTableView
仅绘制当前在视口中的单元格,QItemDelegate
也仅绘制视口中的单元格,因此无论模型中有多少行和列,就效率而言应该大致相同。
不过,我选择了模型方法,因为它不那么麻烦,而且背景是背景而不是 alpha 颜色叠加(选择项目时它混合得很好吗?)。