QCheckBox 的背景颜色在用户检查时与 python 代码设置它检查时不同

Background color of QCheckBox differs when checked by user vs when python code sets it checked

问题总结: 上面三个复选框中的两个有复选标记。其中一个值是使用 Python 代码 self.setwithPythoncode.setChecked(True) 设置的,而另一个值是在应用处于 运行.

时通过用户单击框来设置的

实际结果: 在用户选中的复选框中,复选框小部件部分的背景是蓝色的,但在 python 代码中设置的背景是普通的(或白色的)。

期望的结果: 当我以编程方式设置背景时,如何更改代码以使背景看起来与用户设置时相同,即在实际框中具有蓝色背景。

讨论: 顺便说一句,如果我两次选中 "set with Python code" 按钮,一次取消选中并再次选中它,则会出现蓝色背景。

我尝试过的: 我还没有找到 属性 的 QCheckBox 或 QAbstractButton 来控制可检查方块的背景。我在 Designer 属性列表中找不到任何明显的复选框。

这是Python代码。

from PyQt5.QtWidgets import QApplication
from PyQt5 import QtWidgets, uic


class X(QtWidgets.QTableWidget):
    def __init__(self, ui_file):
        super(X, self).__init__()
        uic.loadUi(ui_file, self)
        self.setwithPythoncode.setChecked(True)


if __name__== '__main__':
    app = QApplication([''])
    window = X("test_check_boxes.ui")
    window.show()
    app.exec_()

这里是test_check_boxes.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>217</width>
    <height>201</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QCheckBox" name="setbyuserclicking">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>122</y>
     <width>161</width>
     <height>18</height>
    </rect>
   </property>
   <property name="sizePolicy">
    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
     <horstretch>0</horstretch>
     <verstretch>0</verstretch>
    </sizepolicy>
   </property>
   <property name="minimumSize">
    <size>
     <width>30</width>
     <height>0</height>
    </size>
   </property>
   <property name="focusPolicy">
    <enum>Qt::NoFocus</enum>
   </property>
   <property name="autoFillBackground">
    <bool>false</bool>
   </property>
   <property name="text">
    <string>Set by user clicking</string>
   </property>
   <property name="checked">
    <bool>false</bool>
   </property>
  </widget>
  <widget class="QCheckBox" name="notsetanywhere">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>18</y>
     <width>141</width>
     <height>18</height>
    </rect>
   </property>
   <property name="sizePolicy">
    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
     <horstretch>0</horstretch>
     <verstretch>0</verstretch>
    </sizepolicy>
   </property>
   <property name="minimumSize">
    <size>
     <width>30</width>
     <height>0</height>
    </size>
   </property>
   <property name="focusPolicy">
    <enum>Qt::NoFocus</enum>
   </property>
   <property name="text">
    <string>Not set anywhere</string>
   </property>
  </widget>
  <widget class="QCheckBox" name="setwithPythoncode">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>70</y>
     <width>181</width>
     <height>18</height>
    </rect>
   </property>
   <property name="sizePolicy">
    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
     <horstretch>0</horstretch>
     <verstretch>0</verstretch>
    </sizepolicy>
   </property>
   <property name="minimumSize">
    <size>
     <width>30</width>
     <height>0</height>
    </size>
   </property>
   <property name="focusPolicy">
    <enum>Qt::NoFocus</enum>
   </property>
   <property name="text">
    <string>Set with Python code</string>
   </property>
   <property name="checked">
    <bool>false</bool>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

经过一些测试,我发现这可能与以下事实有关:当您调用 setChecked(True) 时,QApplication 仍未激活。

您可以通过在 stateChanged 槽中调用 setChecked(True) 来检查。在这种情况下,该应用程序已经处于活动状态,因此可以按预期工作。

class CheckDemo(QWidget):

    def __init__(self, parent = None):
        super(CheckDemo, self).__init__(parent)

        self.layout = QHBoxLayout()
        self.b1 = QCheckBox("Button1", self)
        self.b2 = QCheckBox("Button2", self)
        self.b3 = QCheckBox("Button3", self)

        self.b1.setChecked(False)
        self.b2.setChecked(False)
        self.b3.setChecked(False)

        self.layout.addWidget(self.b1)
        self.layout.addWidget(self.b2)
        self.layout.addWidget(self.b3)
        self.setLayout(self.layout)
        self.setWindowTitle("checkbox demo")

        self.b2.stateChanged.connect(self.stateSlot)

        self.show()

    def stateSlot(self, state):
        self.b3.setChecked(True)

不过我找到了三种解决此问题的方法。

1.更改 PyQt 版本

如果您使用的是最新版本 5.13.2,您可以将其回滚到 5.10.1,您的代码将正常工作。

2。使用 QTimer

这样做会延迟 setChecked 调用。这使 QApplication 有时间处于活动状态。问题是,取决于你的电脑,代码等。它可能无法正常工作,给你带来困难。

class CheckDemo(QWidget):

    def __init__(self, parent = None):
        super().__init__(parent)

        self.layout = QHBoxLayout()
        self.b1 = QCheckBox("Button1", self)
        self.b2 = QCheckBox("Button2", self)
        self.b3 = QCheckBox("Button3", self)

        self.layout.addWidget(self.b1)
        self.layout.addWidget(self.b2)
        self.layout.addWidget(self.b3)

        self.b1.setChecked(False)
        self.b2.setChecked(False)
        self.b3.setChecked(False)

        self.setLayout(self.layout)
        self.setWindowTitle("checkbox demo")
        QTimer.singleShot(500, lambda: self.b2.setChecked(True)) #Here


def main():
    app = QApplication(sys.argv)
    customWidget = CheckDemo()
    app.setTargetObject(ex)
    customWidget.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

3。自定义 QApplication subclass

您可以在 event 方法中捕获 QEvent.ApplicationActivate 并从 class.

中调用 initialize 方法
class MyApp(QApplication):

    def __init__(self, args):
        super().__init__(args)
        self.application_first_time_active = True# You need to know when is the first time application was activated
        self.target_object = None

    def setTargetObject(self, obj):
        self.target_object = obj

    def event(self, event):
         if event.type() == QEvent.ApplicationActivated and self.application_first_time_active:
             self.target_object.initialize()
             self.application_first_time_active = False
         return super().event(event)


class CheckDemo(QWidget):

    def __init__(self, parent = None):
        super().__init__(parent)

        self.layout = QHBoxLayout()
        self.b1 = QCheckBox("Button1", self)
        self.b2 = QCheckBox("Button2", self)
        self.b3 = QCheckBox("Button3", self)

        self.layout.addWidget(self.b1)
        self.layout.addWidget(self.b2)
        self.layout.addWidget(self.b3)

        self.b1.setChecked(False)
        self.b2.setChecked(False)
        self.b3.setChecked(False)

        self.setLayout(self.layout)
        self.setWindowTitle("checkbox demo")

    def initialize(self):
        self.b2.setChecked(True)


def main():
    app = MyApp(sys.argv)
    customWidget = CheckDemo()
    app.setTargetObject(customWidget)# Fixed
    customWidget.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

我想说这可能是最新 qt 版本的错误。我会向您推荐 opening an issue QtCompany。