如何更改未选中元素的样式?

How to change style of an unselected element?

我正在尝试使用 PyQt5 构建文件夹查看器,但遇到了问题。 为了标记选定的文件或目录,我制作了一个 eventFilter,它设置了 QLabel 元素的 属性 'selected' 并对其应用了一些样式。 问题是,当我将 'selected' 设置为 True - file/folder 被选中(应用样式),但是当我尝试将 'selected' 设置为先前选择的元素的 None它正在工作(属性 更改),但样式不会应用于它(它不是取消选择,不会 returns 到未选择状态)。 这是我的代码片段:

import sys
import os

from PyQt5.QtWidgets import (QApplication, QShortcut, QLabel, QPushButton,
                         QGridLayout, QWidget, QMainWindow, QLineEdit,
                         QVBoxLayout, QShortcut, QAction, QMessageBox,
                         QHBoxLayout, QComboBox, QCheckBox, QScrollArea)
from PyQt5.QtGui import QIntValidator, QIcon
from PyQt5.QtCore import Qt, QObject, QEvent, QSize


class MyWindow(QMainWindow):

    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)
        self.setGeometry(600, 300, 700, 500)
        self.setWindowTitle('Folder imitator')
        self.homeDirectory = os.path.splitdrive(os.getcwd())[0]+os.path.sep
        self.currentDirectory = self.homeDirectory
        self.setStyleSheet(open('style.css').read())
        self.selected = None
        self.initUI()

    def initUI(self):
        cenWidget = QWidget(self)
        mainVertLayout = QVBoxLayout(cenWidget)

        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        viewWidg = QWidget()
        viewVertLayout = QVBoxLayout(viewWidg)
        viewVertLayout.installEventFilter(self)
        viewVertLayout.setAlignment(Qt.AlignTop)
        viewVertLayout.setSpacing(0)
        viewVertLayout.setContentsMargins(3, 3, 3, 3)

        self.files = [QLabel(filename) for filename in self.getDirList()]
        for f in self.files:
            f.installEventFilter(self)
            viewVertLayout.addWidget(f)

        scroll.setWidget(viewWidg)

        mainVertLayout.addWidget(scroll)
        mainVertLayout.setContentsMargins(0, 0, 0, 0)
        mainVertLayout.setSpacing(0)
        mainVertLayout.setAlignment(Qt.AlignLeft)

        self.setCentralWidget(cenWidget)

    def getDirList(self):
        return sorted(os.listdir(self.currentDirectory), 
            key=lambda x : 1 if os.path.isdir(os.path.join(
            self.currentDirectory, x)) and not x.endswith('.BIN') else 2)

    def eventFilter(self, obj, event):
        if event.type() == QEvent.MouseButtonPress:
            # I am interested in this part
            if event.button() == Qt.LeftButton:
                if self.selected and self.files[self.selected] != obj:
                    self.files[self.selected].setProperty('selected', None)
                if obj.property('selected') == None:
                    obj.setProperty('selected', True)
                    self.selected = self.files.index(obj)
                else:
                    obj.setProperty('selected', None)
                    self.selected = None
                obj.setStyleSheet('')

        return QObject.event(obj, event)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyWindow()
    window.show()
    app.exec_()

这里是 style.css 文件:

QLabel {
    color: black;
    font-size: 12px;
    background-color: none;
}

QLabel[selected=true] {
    color: #fff;
    background-color: blue;
}

Unselecting the same file that was selected previously by clicking on it again, seems to be working fine, but other file is not unselected automaticaly when another is selected, why is that and how I can resolve this problem? 提前谢谢你。

您必须调用小部件 QStyle 的 unpolish() and polish() 方法:

    def eventFilter(self, obj, event):
        if event.type() == QEvent.MouseButtonPress and obj in self.files:
            if event.button() == Qt.LeftButton:
                if self.selected is None:
                    obj.setProperty("selected", True)
                    self.update_style(obj)
                    self.selected = obj
                elif self.selected is obj:
                    last_state = obj.property("selected")
                    obj.setProperty("selected", None if last_state else True)
                    self.update_style(obj)
                    self.selected = None
                else:
                    self.selected.setProperty("selected", None)
                    obj.setProperty("selected", True)
                    self.update_style(obj)
                    self.update_style(self.selected)
                    self.selected = obj
        return super(MyWindow, self).eventFilter(obj, event)

    @staticmethod
    def update_style(obj):
        obj.style().unpolish(obj)
        obj.style().polish(obj)