I have written a small PyQt5 application with two QListWidgets as shown in the picture. I have set the "fusion" style in order to get comboboxes with background color, and as an undesired result I got this issue with QListWidget selection colors: selection has blue background when it has the focus, which is perfectly fine, but gets a light grey background when the list loses its focus (as in the list on the left), making it hard to read.
I tried different combinations of CSS styling over the widget based on similar snippets for QTableWidgets, but without success.
Any idea of how to change this background color?
EDIT: Given that proposed solution is not working, I have looked for possible differences against your test. It is likely due to the usage of a custom QStyledItemDelegate I got from How to display partially bold text in QListWidgetItem with QtCore.Qt.UserRole
from PyQt5 import QtCore, QtGui, QtWidgets
class HTMLDelegate(QtWidgets.QStyledItemDelegate):
'''
The roles >= Qt::UserRole are not used by Qt by default so it can be used for any purpose,
for example to save additional information, in this case it is not the solution.
One possible solution is to use a delegate to render the HTML.
(Extracted from https://stackoverflow.com/questions/53569768/how-to-display-partially-bold-text-in-qlistwidgetitem-with-qtcore-qt-userrole)
'''
def __init__(self, parent=None):
super(HTMLDelegate, self).__init__(parent)
self.doc = QtGui.QTextDocument(self)
def paint(self, painter, option, index):
painter.save()
options = QtWidgets.QStyleOptionViewItem(option)
self.initStyleOption(options, index)
self.doc.setHtml(options.text)
options.text = ""
style = QtWidgets.QApplication.style() if options.widget is None \
else options.widget.style()
style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, options, painter)
ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()
if option.state & QtWidgets.QStyle.State_Selected:
ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(
QtGui.QPalette.Active, QtGui.QPalette.HighlightedText))
else:
ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(
QtGui.QPalette.Active, QtGui.QPalette.Text))
textRect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options, None)
if index.column() != 0:
textRect.adjust(5, 0, 0, 0)
constant = 4
margin = (option.rect.height() - options.fontMetrics.height()) // 2
margin = margin - constant
textRect.setTop(textRect.top() + margin)
painter.translate(textRect.topLeft())
painter.setClipRect(textRect.translated(-textRect.topLeft()))
self.doc.documentLayout().draw(painter, ctx)
painter.restore()
def sizeHint(self, option, index):
return QtCore.QSize(self.doc.idealWidth(), self.doc.size().height())
Hence, I guess that I should modify the part where colors are set for the QPalette. Nevertheless, QStyle::State_HasFocus is not being used here, so I don't understand why it is not working. Any idea of how to fix it now?
As a parallel question: Where is the definition for all the CSS possibilities for QT widgets and its subelements? I would like to be able to explore it by myself instead of bothering stackoverflow users with this kind of questions for simple CSS code in the future :)
You cannot rely on stylesheets whenever there is custom drawing involved using QPalette colors as a reference: stylesheets override the styling, and whenever colors are specified the palette is also ignored (at least for the states/properties specified in the stylesheet).
The palette knows nothing about the stylesheets, and it's actually the other way around: the stylesheets use the palette (in fact, you can use palette roles in stylesheets).
There's no way to programmatically access the colors used in stylesheets.
You have two possibilities:
if not option.state & QtWidgets.QStyle.State_HasFocus:
options.palette.setColor(QtGui.QPalette.Highlight, QtCore.Qt.darkGray)
style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, options, painter)
# ...
if (option.state & QtWidgets.QStyle.State_Selected and
option.state & QtWidgets.QStyle.State_HasFocus):
ctx.palette.setColor(QtGui.QPalette.Text, option.palette.color(
QtGui.QPalette.Active, QtGui.QPalette.HighlightedText))
else:
# ...