Как изменить стиль невыбранного элемента? - PullRequest
1 голос
/ 24 февраля 2020

Я пытаюсь создать средство просмотра папок с PyQt5, и я столкнулся с проблемой. Чтобы отметить выбранный файл или каталог, я создал eventFilter, который устанавливает свойство selected для элемента QLabel и применяет к нему некоторые стили. Проблема в том, что когда я устанавливаю «selected» в значение True - файл / папка выбирается (к нему применяются стили), но когда я пытаюсь установить «selected» в значение «Ни один из ранее выбранных элементов», он работает (свойство изменяется), но к нему не применяются стили (не отменяет выбор, не возвращает в невыбранное состояние). Вот фрагмент моего кода:

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

А вот стиль. css file:

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

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

Отмена выбора того же файла, который был выбран ранее, нажав на него еще раз , кажется, работает нормально, но другой файл не выбирается автоматически, когда выбирается другой, почему и как я могу решить эту проблему? Заранее спасибо.

1 Ответ

2 голосов
/ 24 февраля 2020

Вам нужно вызвать метод unpolish() и polish() виджета QStyle:

    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)
...