首页 > 解决方案 > 选中 CheckBox 时更改整个窗口的样式表

问题描述

因此,我有这个GUI,每当检查复选框时,我都试图更改其样式表。这是我的代码的简化版本:

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'”。关于如何使它工作的任何想法?

标签: pythonpython-3.xpyqtpyqt5

解决方案


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

一种可能的解决方案是使用 lambda 进行连接,该 lambda 还将Form实例返回给方法:

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

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

除此之外,您的代码还有一个更概念性的问题,那就是您正在尝试编辑生成的文件pyuic(或试图模仿其行为),这是永远不应该做的事情。要正确使用这些文件,您只需要导入它们,并使用官方文档中关于使用 Designer建议的方法之一。

最常见和最简单的方法是多重继承方法,您可以从小部件类pyuic 类中继承。为了使用下面的代码,重新生成 python 文件pyuic并命名它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_())

推荐阅读