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

2024-05-19 07:57:40 发布

您现在位置:Python中文网/ 问答频道 /正文

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

基于QTableWidgets的类似代码片段,我在小部件上尝试了不同的CSS样式组合,但没有成功

你知道如何改变背景色吗

enter image description here

编辑:鉴于建议的解决方案不起作用,我已经针对您的测试寻找了可能的差异。这可能是因为使用了我从How to display partially bold text in QListWidgetItem with QtCore.Qt.UserRole获得的定制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 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())

因此,我想我应该修改为Qpalete设置颜色的部分。然而,这里没有使用QStyle::State_HasFocus,所以我不明白它为什么不起作用。你知道现在怎么修吗

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


Tags: totextselfindexdocstyleoptionsoption
2条回答

当涉及使用Qpalete颜色作为参考的自定义图形时,不能依赖样式表:样式表覆盖样式,并且每当指定颜色时,调色板也会被忽略(至少对于样式表中指定的状态/属性)

调色板对样式表一无所知,事实上恰恰相反:样式表使用调色板(事实上,您可以使用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:
            # ...

它可以在::item子控件、:selected伪状态和:!active伪状态中设置

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_())

相关问题 更多 >

    热门问题