Reputation: 346
I subclassed a QStyledItemDelegate
to change the highlight color of the selections, and if there is a QColor
in ForegroundRole and BackgroundRole I will try to blend two colors.
However, when I'm trying to select a row in the tableview, following error message shows up:
TypeError: arguments did not match any overloaded call:
setColor(self, QPalette.ColorGroup, QPalette.ColorRole, Union[QColor, Qt.GlobalColor, QGradient]): argument 1 has unexpected type 'ColorRole'
setColor(self, QPalette.ColorRole, Union[QColor, Qt.GlobalColor, QGradient]): argument 2 has unexpected type 'NoneType'
and terminal shows:
QPainter::begin: A paint device can only be painted by one painter at a time.
QPainter::setCompositionMode: Painter not active
QBackingStore::endPaint() called with active painter; did you forget to destroy it or call QPainter::end() on it?
Here is my implementation:
class StyleDelegateForTable_List(QStyledItemDelegate):
"""
Customize highlight style for ListView & TableView
"""
def __init__(self, parent):
super().__init__(parent)
self.hightColor = QtGui.QColor("#0096ff")
def paint(self, painter, option: QtWidgets.QStyleOptionViewItem, index):
self.initStyleOption(option, index)
if (option.state & QtWidgets.QStyle.StateFlag.State_Selected and
option.state & QtWidgets.QStyle.StateFlag.State_Active):
# get foreground color,
# don't know where to set foreground color though...
fg = self.getColor(index, isBG = False)
# get background color
bg = self.getColor(index, isBG = True)
# set highlight color
option.palette.setColor(QtGui.QPalette.ColorRole.Highlight,
self.mixColors(bg))
QStyledItemDelegate.paint(self, painter, option, index)
def getColor(self, index: QModelIndex, isBG = True) -> QtGui.QColor:
parentWidget = self.parent()
model = parentWidget.model()
dataRole = Qt.ItemDataRole.BackgroundRole if isBG else Qt.ItemDataRole.ForegroundRole
# TableView
if isinstance(parentWidget, QtWidgets.QTableView):
if isinstance(model, QSortFilterProxyModel):
# proxy model
sourceIndex = model.mapToSource(index)
return model.sourceModel().data(sourceIndex, dataRole)
elif isinstance(model, TestDataTableModel):
# abstract table model
return model.data(index, dataRole)
# ListView
if isinstance(parentWidget, QtWidgets.QListView):
if isinstance(model, QSortFilterProxyModel):
# all of listView uses proxyModel
sourceIndex = model.mapToSource(index)
return model.sourceModel().data(sourceIndex, dataRole)
return QtGui.QColor("#000000")
def mixColors(self, src) -> QtGui.QColor:
if isinstance(src, QtGui.QColor):
r = int(src.red()*0.7 + self.hightColor.red()*0.3)
g = int(src.green()*0.7 + self.hightColor.green()*0.3)
b = int(src.blue()*0.7 + self.hightColor.blue()*0.3)
return QtGui.QColor(r, g, b)
else:
# I intended to mix default bg or fg color
# with highlight color but default is None.
# return hightlight color for now
self.hightColor
I tried to set a breakpoint in getColor
, but my app just crashed, what did I do wrong here?
Edit:
This question is invalid, as @ musicamante points out, mixColors
returns None instead of hightlight color if the original Background/Foreground is None.
I will keep this question in case someone needs the same functionality.
Upvotes: 0
Views: 93