PyQt5:当列表失去焦点时设置QListWidget选择颜色

PyQt5: setting QListWidget selection color when the list loses focus

我编写了一个带有两个 QListWidget 的小型 PyQt5 应用程序,如图所示。我已经设置了“融合”样式以获得具有背景颜色的组合框,并且作为一个不希望的结果我遇到了 QListWidget 选择颜色的问题:当它具有焦点时选择具有蓝色背景,这非常好,但是得到了光列表失去焦点时的灰色背景(如左侧列表),难以阅读。

我根据 QTableWidgets 的类似片段尝试了 CSS 样式的不同组合,但没有成功。

知道如何更改此背景颜色吗?

编辑:鉴于建议的解决方案不起作用,我已经寻找与您的测试可能存在的差异。这可能是由于使用了我从

获得的自定义 QStyledItemDelegate
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 
    '''
    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())

因此,我想我应该修改为QPalette设置颜色的部分。尽管如此,这里没有使用 QStyle::State_HasFocus,所以我不明白为什么它不起作用。现在知道如何修复它吗?

作为平行问题:QT 小部件及其子元素的所有 CSS 可能性的定义在哪里?我希望能够自己探索它,而不是为了将来的简单 CSS 代码而用这种问题来打扰 Whosebug 用户:)

可在::itemsub-control、:selectedpseudo-state、:!activepseudo-state、

中设置
QListWidget::item:selected:!active {
    background: #17d;
}

测试示例:

import sys
from PyQt5.QtWidgets import *

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle('fusion')
    app.setStyleSheet('''
    QListWidget::item:selected:!active {
        background: lightBlue;
        color: black;
    }''')
    items = ['2020-11-27'] * 6
    x = QListWidget(); x.addItems(items)
    y = QListWidget(); y.addItems(items)
    window = QWidget()
    hbox = QHBoxLayout(window)
    hbox.addWidget(x); hbox.addWidget(y)
    window.show()
    sys.exit(app.exec_())

只要涉及使用 QPalette 颜色作为参考的自定义绘图,就不能依赖样式表:样式表 覆盖 样式,并且无论何时指定颜色,调色板也会被忽略(在至少对于样式表中指定的 states/properties。

调色板对样式表一无所知,实际上恰恰相反:样式表使用调色板(事实上,你可以使用 palette roles in stylesheets).
没有 方式以编程方式访问样式表中使用的颜色。

你有两种可能:

  1. 在没有焦点时更改突出显示项目的背景颜色,绘制项目之前:
        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)
        # ...
  1. 仅在项目被选中时设置文本颜色并且有焦点:
        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:
            # ...