悬停动画在 PyQT5 的 QSS 中不起作用

Hover animation does not work in QSS in PyQT5

我正在尝试在 PyQT5 中创建我的第一个 UI。但是,我无法向我的按钮添加悬停动画,而且我不明白为什么它不起作用。

我正在尝试使用此样式表,而不是关闭 QPushButton#authenticate_button:悬停我也尝试了#authenticate_button 和 QPushButton,但似乎没有任何效果:

self.background_window.setStyleSheet("#authenticate_button {\n"
                                    "color: white;\n"
                                    "background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,stop: 0 rgba(0,145,224,255), stop: 1 rgba(0,250,215,255)) ;\n"
                                    "border-radius: 0;\n"
                                    "border-radius: 20px;\n"
                                    "}\n"
                                    "\n"
                                    "#background_window {\n"
                                    "border-radius: 10px;\n"
                                    "background-color: rgb(50, 50, 50);\n"
                                    "}\n"
                                    "\n"
                                    "#key_textfield {\n"
                                    "background-color: transparent;\n"
                                    "border: 2px solid grey;\n"
                                    "border-radius: 10px;\n"
                                    "}\n"
                                    "QPushButton#authenticate_button:hover {\n"
                                    "border-radius: 30px;\n"
                                    "}\n"
                                    "")

目前看起来像这样,但是当我将鼠标悬停在该元素上时没有任何变化。

这是完整的代码,抱歉,我尽量缩短了它,但我不想遗漏重要的细节:

class Ui_authenticate_window(object):
    def setupUi(self, authenticate_window):
        authenticate_window.setObjectName("authenticate_window")
        authenticate_window.setEnabled(False)
        authenticate_window.resize(300, 450)
        authenticate_window.setMaximumSize(QtCore.QSize(300, 450))

        self.centralwidget = QtWidgets.QWidget(authenticate_window)
        self.centralwidget.setEnabled(False)

     
        self.background_window = QtWidgets.QFrame(self.centralwidget)
        self.background_window.setGeometry(QtCore.QRect(10, 60, 280, 380))
        self.background_window.setStyleSheet("#authenticate_button {\n"
                                            "color: white;\n"
                                            "background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,stop: 0 rgba(0,145,224,255), stop: 1 rgba(0,250,215,255)) ;\n"
                                            "border-radius: 0;\n"
                                            "border-radius: 20px;\n"
                                            "}\n"
                                            "\n"
                                            "#background_window {\n"
                                            "border-radius: 10px;\n"
                                            "background-color: rgb(50, 50, 50);\n"
                                            "}\n"
                                            "\n"
                                            "#key_textfield {\n"
                                            "background-color: transparent;\n"
                                            "border: 2px solid grey;\n"
                                            "border-radius: 10px;\n"
                                            "}\n"
                                            "QPushButton#authenticate_button:hover {\n"
                                            "border-radius: 30px;\n"
                                            "}\n"
                                            "")

        self.background_window.setObjectName("background_window")
        self.authenticate_button = QtWidgets.QPushButton(self.background_window)
      
        self.authenticate_button.setGeometry(QtCore.QRect(10, 320, 260, 41))
        font = QtGui.QFont()
        font.setFamily("Montserrat")
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(75)
        self.authenticate_button.setFont(font)
        

        self.authenticate_button.setObjectName("authenticate_button")
        
        self.key_textfield = QtWidgets.QLineEdit(self.background_window)
        self.key_textfield.setGeometry(QtCore.QRect(10, 270, 260, 25))
        font = QtGui.QFont()
        font.setFamily("Arial")
        self.key_textfield.setFont(font)
        self.key_textfield.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.key_textfield.setObjectName("key_textfield")
        self.logo_icon = QtWidgets.QToolButton(self.centralwidget)
        self.logo_icon.setGeometry(QtCore.QRect(100, 10, 100, 100))
        self.logo_icon.setStyleSheet("#logo_icon {\n"
        "background-color: transparent;\n"
        "}")
        
        creation_logo = QtGui.QIcon()
        creation_logo.addPixmap(QtGui.QPixmap("required/images/creation.ico"), QtGui.QIcon.Disabled, QtGui.QIcon.Off)
        self.logo_icon.setIcon(creation_logo)
        self.logo_icon.setIconSize(QtCore.QSize(1000000, 100000))
        self.logo_icon.setObjectName("logo_icon")
        authenticate_window.setCentralWidget(self.centralwidget)

        self.retranslateUi(authenticate_window)
        QtCore.QMetaObject.connectSlotsByName(authenticate_window)

    def retranslateUi(self, authenticate_window):
        _translate = QtCore.QCoreApplication.translate
        authenticate_window.setWindowTitle(_translate("authenticate_window", "creation. - Authentication."))
        self.authenticate_button.setText(_translate("authenticate_window", "Authenticate."))

您正在禁用 window 及其中央小部件。

当小部件被禁用时,它将不会接收任何鼠标事件,包括悬停事件。显然,当父窗口小部件被禁用时,任何子窗口小部件(以及任何级别的子窗口小部件)都将被禁用。[1]

因此,请考虑仅禁用父项(主要 window),因为重新启用已禁用的小部件只会重新启用 的子项明确禁用。在您的情况下,如果您在 window 上调用 setEnabled(True),它将无法正常工作,因为中央小部件已被禁用。

然后,确保对象名称选择器也使用 class,因为如果您不够小心,您可能会添加一个对象名称相同但 class 不同的子部件,即使不应该,它也会继承样式表。

此外,请考虑使用 layout managers (they can be easily created in Designer too),因为使用固定几何形状通常被认为是不好的做法,并且几乎总是会导致显示问题(请记住,您在屏幕上看到的是 never 其他人在他们的中看到的内容,特别是对于显示文本的小部件,更重要的是如果您使用的是非默认字体)。

[1] enabled property documentation says that the only exception are subclasses of QAbstractButton (which includes QPushButton), which accept mouse events even when disabled. This might be counterintuitive and could be confusing; the reality is that accepting an event doesn't mean that it's actually handled, so it doesn't mean that disabled buttons actually receive and react to those events (because they shouldn't!) but only that event() returns True 而不是 False (这是任何其他小部件 return如果禁用),这样事件就不会传播到父级。