[PySide] custom paint delegate for table keeps redrawing clicked cell
Frank Rueter
frank at ohufx.com
Sun Nov 2 07:44:28 CET 2025
Hi all,
I have this example code below which uses a delegate to paint a selected
row in a QTableWidget with custom colours and a border.
But for some reason that I do not understand the font colours change as
well as you can see in the attached screen recording.
I am particularly curious about why the clicked cell repaints itself split
seconds after my custom paint event (and how I can prevent that).
Any help would be greatly appreciated!
Cheers,
frank
from PySide6.QtWidgets import (
QApplication, QTableWidget, QTableWidgetItem, QStyledItemDelegate,
QStyleOptionViewItem, QStyle
)
from PySide6.QtGui import QPainter, QPen, QColor
# Dark blue colors for selection
COLORS = {
"row_border": QColor("#003366"),
"row_fill": QColor("#336699"),
"text": QColor("black")
}
class CutTableDelegate(QStyledItemDelegate):
"""Draws a dark blue fill for selected rows.
"""
#ToDo: the text colour changes when it shouldn't
def paint(self, painter, option, index):
option_no_select = QStyleOptionViewItem(option)
option_no_select.state &= ~QStyle.State_Selected # prevent
default selection background
# Draw row background if selected
if option.state & QStyle.State_Selected:
table = index.model().parent()
if table:
row_rect = table.visualRect(table.model().index(index.row(), 0))
for col in range(1, table.columnCount()):
row_rect =
row_rect.united(table.visualRect(table.model().index(index.row(),
col)))
painter.setPen(QPen(COLORS["row_border"], 2))
painter.setBrush(COLORS["row_fill"])
painter.drawRect(row_rect.adjusted(0, 0, -1, -1))
# Draw the cell text using fixed color
painter.save()
painter.setPen(QPen(COLORS["text"]))
super().paint(painter, option_no_select, index)
painter.restore()
if __name__ == "__main__":
app = QApplication([])
table = QTableWidget(5, 3)
table.setHorizontalHeaderLabels(["Shot Name", "Duration", "Status"])
table.setItemDelegate(CutTableDelegate(table))
table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
# Sample data
data = [
["Shot 1", "10", "Ready"],
["Shot 2", "12", "Pending"],
["Shot 3", "8", "Done"],
["Shot 4", "15", "Ready"],
["Shot 5", "5", "Pending"],
]
for row_idx, row_data in enumerate(data):
for col_idx, text in enumerate(row_data):
table.setItem(row_idx, col_idx, QTableWidgetItem(text))
table.resize(500, 300)
table.show()
app.exec()
--
Frank Rueter I VFX Supervisor | OHUfx | +64 21 110 7919
Aotearoa | New Zealand
www.ohufx.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20251102/b5462772/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: delegate_issues_with_table.mov
Type: video/quicktime
Size: 305157 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20251102/b5462772/attachment-0001.mov>
More information about the PySide
mailing list