同时有两个或多个小部件的悬停效果?

Hover Effect for Two or More Widgets at a same time?

如何同时为两个或多个QLabel制作悬停效果?例如,在我的代码中,我需要一次为 Lbl1 和 Lbl2 悬停效果。 (鼠标进入 QLabel 1 或 QLabel 2,两个 QLabel 都会产生悬停效果)

from PyQt5 import QtWidgets

class Hover_Multiple(QtWidgets.QWidget):
    def __init__(self):
        super(). __init__()
        self.setWindowTitle("Hover Effects")
        self.lbl1 = QtWidgets.QLabel("Python")
        self.lbl1.setFixedSize(100,50)
        self.lbl1.setStyleSheet(mystyle())

        self.lbl2 = QtWidgets.QLabel("PyQt5")
        self.lbl2.setStyleSheet(mystyle())
        self.lbl2.setFixedSize(100,50)

        self.hbox = QtWidgets.QHBoxLayout()
        self.hbox.addStretch()
        self.hbox.addWidget(self.lbl1)
        self.hbox.addWidget(self.lbl2)
        self.hbox.addStretch()
        self.hbox.setSpacing(0)
        self.hbox.setContentsMargins(0,0,0,0)
        self.setLayout(self.hbox)

def mystyle():
    return"""
    QLabel  
    {
    background-color:lightgreen;
    min-height : 25%; min-width : 40%;
    border:0px solid;border-color:red;
    text-align:centre ;font-size :10pt;  font-family:Trebuchet MS; color:Black; padding : 2px;
    }
    
    QLabel::hover
    {
    background-color: red;
    color :white;
    }
    """

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    mainwindow = Hover_Multiple()
    mainwindow.show()
    sys.exit(app.exec_())

一个可能的解决方案是使用一个 qproperty 作为改变绘画的标志,并且当某些小部件被 QEvent::HoverEnterQEvent::HoverLeave 触发时,必须在小部件中更改该 qproperty事件,这可以使用事件过滤器来完成。

from PyQt5 import QtCore, QtWidgets


class HoverHelper(QtCore.QObject):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._widgets = []

    @property
    def widgets(self):
        return self._widgets

    def add_widget(self, widget):
        if not isinstance(widget, QtWidgets.QWidget):
            raise TypeError(f"{widget} must be QWidget object")
        widget.installEventFilter(self)
        widget.setAttribute(QtCore.Qt.WA_Hover)
        self.widgets.append(widget)

    def eventFilter(self, obj, event):
        if obj in self.widgets:
            if event.type() == QtCore.QEvent.HoverEnter:
                self.change_property(True)
            elif event.type() == QtCore.QEvent.HoverLeave:
                self.change_property(False)
        return super().eventFilter(obj, event)

    def change_property(self, hovered):
        for widget in self.widgets:
            widget.setProperty("hovered", hovered)
            widget.style().polish(widget)


class Hover_Multiple(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Hover Effects")
        self.setStyleSheet(style_sheet())

        self.lbl1 = QtWidgets.QLabel("Python")
        self.lbl1.setFixedSize(100, 50)

        self.lbl2 = QtWidgets.QLabel("PyQt5")
        self.lbl2.setFixedSize(100, 50)

        lay = QtWidgets.QHBoxLayout(self)
        lay.addStretch()
        lay.addWidget(self.lbl1)
        lay.addWidget(self.lbl2)
        lay.addStretch()
        lay.setSpacing(0)
        lay.setContentsMargins(0, 0, 0, 0)

        helper = HoverHelper(self)
        helper.add_widget(self.lbl1)
        helper.add_widget(self.lbl2)


def style_sheet():
    return """
    QLabel{
        background-color: lightgreen;
        min-height: 25%;
        min-width: 40%;
        border: 0px solid;
        border-color: red;
        text-align: center;
        font-size: 10pt;
        font-family: Trebuchet MS;
        color: black;
        padding: 2px;
    }
    QLabel[hovered="true"]{
        background-color: red;
        color: white;
    }
    """


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    mainwindow = Hover_Multiple()
    mainwindow.show()
    sys.exit(app.exec_())