pythoncolorspyqt5qtableviewqstyleditemdelegate

Changing the font color of a QTableView after replacing the default editor with an ItemDelegate QTextEdit in PyQt5


I am currently trying to add a multiline text editor to the PandasGUI application and have implemented the solution found here: Make row of QTableView expand as editor grows in height

I am using the qtstylish.dark() stylesheet for the application so I would like the text of the QTableview to be white. It is currently black and has been steadfastly resisting my efforts to change the text color.

The reimplemented paint function currently looks like this:

def paint(self, painter, option, index):
    # Remove dotted border on cell focus.  https://stackoverflow.com/a/55252650/3620725
    if option.state & QtWidgets.QStyle.State_HasFocus:
        option.state = option.state ^ QtWidgets.QStyle.State_HasFocus
    
    self.initStyleOption(option, index)
    painter.save()
    doc = QtGui.QTextDocument()
    doc.setDocumentMargin(2)
    doc.setTextWidth(option.rect.width())
    doc.setHtml(option.text)
    option.text = ""
    option.widget.style().drawControl(
        QtWidgets.QStyle.CE_ItemViewItem, option, painter)
    painter.translate(option.rect.left(), option.rect.top())
    doc.drawContents(painter)
    painter.restore()

Some of the things I have tried adding to the function:

painter.setPen(QColor(255, 255, 255, 200))
painter.setPen(QtGui.QPen(QtCore.Qt.white))
option.palette.setColor(QPalette.Normal, QPalette.Foreground, Qt.white)
doc.setDefaultStyleSheet('color: rgb(255, 255, 255);')

I have also tried reimplementing the drawContents and the initStyleOption function without finding success in changing the font color.


Solution

  • QTextDocument by default uses the global application palette (which might be overridden by stylesheets).

    If the widget uses a different palette, then QTextDocument.drawContents() won't be enough, and a proper context must be used.

    The solution is to use the document layout and create a PaintContext instance with the alternate palette:

        def paint(self, painter, option, index):
            # ...
            layout = doc.documentLayout()
            ctx = layout.PaintContext()
            ctx.palette = option.palette
            layout.draw(painter, ctx)
            painter.restore()
    

    Note: you might need to setClipRect() the painter to restrict drawing within the index rectangle, otherwise you might have some drawing artifacts (especially when hovering and scrolling). I couldn't test your code, but the following should suffice:

            # after translation
            clip = QtCore.QRectF(0, 0, 
                option.rect.width(), option.rect.height())
            painter.setClipRect(clip)