【问题标题】:Background color of QCheckBox differs when checked by user vs when python code sets it checked用户检查时 QCheckBox 的背景颜色与 python 代码设置它检查时的背景颜色不同
【发布时间】:2019-12-09 02:00:35
【问题描述】:

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

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

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

讨论: 顺便说一句,如果我两次选中“使用 Python 代码设置”按钮,一次取消选中,然后再次选中它,则会出现蓝色背景。

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

这是 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>

【问题讨论】:

  • 我怀疑这个蓝色是在最后一个 QCheckBox 中给出的,因为它有焦点。如果单击“未在任何地方设置”,第三个 QCheckBox 仍然是蓝色?
  • 是的。通过选中该框设置颜色后,在我选中另一个框后它保持设置。
  • 感谢 @eyllanesc 添加我忘记复制的导入语句。如果有人在看这个,他们应该一定会看到他的编辑。

标签: python pyqt pyqt5 qcheckbox


【解决方案1】:

经过一些测试,我发现这可能与当您调用 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 子类

您可以在event 方法中捕获QEvent.ApplicationActivate,并从您的类中调用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 版本的一个错误。我会向 QtCompany 推荐你 opening an issue

【讨论】:

  • 很好的回复。我确实向 Qt 报告了它,并且正在使用您的 QTimer 解决方法。在您的第三个解决方案中,“app.setTargetObject(ex)”中“ex”的定义是什么?
  • 应该是customWidget。我现在已经修好了。 @WesR
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-13
  • 1970-01-01
  • 2015-11-09
  • 2014-03-08
相关资源
最近更新 更多