选中 CheckBox 时更改整个 window 的样式 Sheet

Changing Style Sheet of the whole window when CheckBox is checked

所以我有这个 GUI,我试图在选中复选框时更改它的样式 Sheet。这是我的代码的简化版本:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys
style_sheet = "#Form{background-color: rgb(255,255,255);}"
inverted_ss = "#Form{background-color: rgb(0,0,0);}"


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(698, 453)
        Form.setStyleSheet(style_sheet)

        #some design preferences here, including frame_19 and horizontalLayout_5 as seen below

        self.checkBox = QtWidgets.QCheckBox(self.frame_19)
        self.checkBox.setEnabled(True)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.checkBox.sizePolicy().hasHeightForWidth())
        self.checkBox.setSizePolicy(sizePolicy)
        self.checkBox.setMinimumSize(QtCore.QSize(29, 25))
        self.checkBox.setMaximumSize(QtCore.QSize(29, 50))
        self.checkBox.setBaseSize(QtCore.QSize(25, 25))
        self.checkBox.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.checkBox.setAutoFillBackground(False)
        self.checkBox.setText("")
        self.checkBox.setIconSize(QtCore.QSize(21, 21))
        self.checkBox.setCheckable(True)
        self.checkBox.stateChanged.connect(self.mode_change)
        self.checkBox.setTristate(False)
        self.checkBox.setObjectName("checkBox")
        self.horizontalLayout_5.addWidget(self.checkBox)

        #some more design preferences here

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

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "App"))

    def mode_change(self, state):
        if state == QtCore.Qt.Checked:
            Form.setStyleSheet(inverted)
        else:
            Form.setStyleSheet(style_sheet)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

问题是,它给了我一个警告:“未解决的参考:'Form'”。知道如何让它发挥作用吗?

在您的代码中,Form 仅用作 local 变量,用作 setupUiretranslateUi 函数的参数。由于在您的 mode_change 函数中没有这样的参数,因此 python 崩溃,因为该引用在函数范围内不存在。

一个可能的解决方案是使用 lambda 进行连接,该 lambda 也 returns Form 实例到方法:

        # ...
        self.checkBox.stateChanged.connect(lambda state: self.mode_change(Form, state))
        # ...

    def mode_change(self, Form, state):
        # ...

除此之外,您的代码还有一个 概念性 问题,那就是您正在尝试编辑使用 pyuic 生成的文件(或试图模仿它的行为),这是 永远不会 应该做的事情。要正确使用这些文件,您只需要 import 它们,并使用有关 using Designer.

的官方文档中建议的方法之一

最常见和简单的方法是 多重继承 方法,您可以从小部件 class 中继承class和 pyuic class。为了使用以下代码,使用 pyuic 重新生成 python 文件并将其命名为 ui_Form.py.

from PyQt5 import QtWidgets
from ui_Form import Ui_Form

style_sheet = "#Form{background-color: rgb(255,255,255);}"
inverted_ss = "#Form{background-color: rgb(0,0,0);}"

class MyForm(QtWidgets.QWidget, Ui_Form):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)

        self.checkBox.stateChanged.connect(self.mode_change)

    def mode_change(self, state):
        if state == QtCore.Qt.Checked:
            self.setStyleSheet(inverted)
        else:
            self.setStyleSheet(style_sheet)

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