📌  相关文章
📜  PyQt5 - 单击时设置未选中的 CheckBox 指示器背景颜色(1)

📅  最后修改于: 2023-12-03 15:18:46.557000             🧑  作者: Mango

PyQt5 - 单击时设置未选中的 CheckBox 指示器背景颜色

在 PyQt5 中,可以使用 QSS(Qt样式表) 来设置 CheckBox 的背景颜色。但是,如果要设置未选中的 CheckBox 指示器的背景颜色,在未选中状态下单击 CheckBox ,这种情况下 QSS 并不起作用。这篇文章将介绍如何在单击 CheckBox 时设置未选中的 CheckBox 指示器的背景颜色。

实现方法

为了实现上述功能,我们需要使用 QProxyStyledrawPrimitive 来绘制 CheckBox 的指示器。下面是实现该功能的示例代码:

from PyQt5.QtWidgets import QApplication, QCheckBox
from PyQt5.QtGui import QColor, QPainter, QPalette, QMouseEvent
from PyQt5.QtCore import QPoint, QSize, Qt, QRect
from PyQt5.QtStyle import QStyle, QProxyStyle


class CheckBoxStyle(QProxyStyle):
    def drawPrimitive(self, element, option, painter, widget=None):
        if element == QStyle.PE_IndicatorCheckBox:
            state = option.state & ~(QStyle.State_On | QStyle.State_Off)
            if option.state & QStyle.State_On:
                if option.state & QStyle.State_Enabled:
                    painter.setBrush(QColor(0, 255, 0, 100))
                else:
                    painter.setBrush(QColor(0, 255, 0, 50))
            else:
                if option.state & QStyle.State_Enabled:
                    painter.setBrush(QColor(255, 0, 0, 100))
                else:
                    painter.setBrush(QColor(255, 0, 0, 50))
            if option.state & (QStyle.State_On | QStyle.State_Off):
                self.drawPrimitive(QStyle.PE_IndicatorViewItemCheck, option, painter, widget)
            return

        super().drawPrimitive(element, option, painter, widget)


class MyCheckBox(QCheckBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setCheckable(True)
        self.setStyle(CheckBoxStyle())

    def sizeHint(self):
        return QSize(20, 20)

    def mousePressEvent(self, event: QMouseEvent) -> None:
        if event.button() == Qt.LeftButton:
            self.toggle()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing, True)
        self.initStyleOption(self.styleOption())
        self.style().drawControl(QStyle.CE_CheckBox, self.styleOption(), painter, self)

上面的代码中,我们创建了一个继承自 QCheckBoxMyCheckBox 类,并在其中重写了 sizeHintmousePressEventpaintEvent 方法。其中,sizeHint 方法设置 CheckBox 的大小,mousePressEvent 方法实现在单击时设置 CheckBox 选中状态,并调用 toggle 方法切换 CheckBox 的选中状态。paintEvent 方法则用于绘制 CheckBox ,在该方法中使用 QPainter 来进行定制化绘制。

为了绘制指示器的背景颜色,我们需要创建一个继承自 QProxyStyleCheckBoxStyle 类,并重写 drawPrimitive 方法。在该方法中,我们判断当前 CheckBox 是否选中,并根据选中状态设置指示器的背景颜色。

最后,在主函数中创建 QApplication 和 MyCheckBox 实例,然后运行程序即可看到单击时设置未选中的 CheckBox 指示器的背景颜色的效果。

结论

在 PyQt5 中,我们可以使用 QSS 来设置 CheckBox 的背景颜色,但是在单击时设置未选中的 CheckBox 指示器的背景颜色,我们需要使用 QProxyStyle 和 drawPrimitive 来绘制 CheckBox 的指示器,以实现该功能。

完整的代码示例可在下方获取:

from PyQt5.QtWidgets import QApplication, QCheckBox
from PyQt5.QtGui import QColor, QPainter, QPalette, QMouseEvent
from PyQt5.QtCore import QPoint, QSize, Qt, QRect
from PyQt5.QtStyle import QStyle, QProxyStyle


class CheckBoxStyle(QProxyStyle):
    def drawPrimitive(self, element, option, painter, widget=None):
        if element == QStyle.PE_IndicatorCheckBox:
            state = option.state & ~(QStyle.State_On | QStyle.State_Off)
            if option.state & QStyle.State_On:
                if option.state & QStyle.State_Enabled:
                    painter.setBrush(QColor(0, 255, 0, 100))
                else:
                    painter.setBrush(QColor(0, 255, 0, 50))
            else:
                if option.state & QStyle.State_Enabled:
                    painter.setBrush(QColor(255, 0, 0, 100))
                else:
                    painter.setBrush(QColor(255, 0, 0, 50))
            if option.state & (QStyle.State_On | QStyle.State_Off):
                self.drawPrimitive(QStyle.PE_IndicatorViewItemCheck, option, painter, widget)
            return

        super().drawPrimitive(element, option, painter, widget)


class MyCheckBox(QCheckBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setCheckable(True)
        self.setStyle(CheckBoxStyle())

    def sizeHint(self):
        return QSize(20, 20)

    def mousePressEvent(self, event: QMouseEvent) -> None:
        if event.button() == Qt.LeftButton:
            self.toggle()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing, True)
        self.initStyleOption(self.styleOption())
        self.style().drawControl(QStyle.CE_CheckBox, self.styleOption(), painter, self)


if __name__ == '__main__':
    app = QApplication([])
    cb = MyCheckBox()
    cb.show()
    app.exec()

参考链接: