Окно с QCheckBox

Имеется окно с QCheckBox (chech.py). По умолчанию выставлены три галки checkbox (п.1, п2, п3) и четвертая галка checkbox ("Выбрать все папки") – пока первые три checkbox имеют статус True. Если снять одну из трех галок checkbox (п.1, п2, п3), то четвертая галка checkbox ("Выбрать все папки") – снимается (скриншот №1).

Трудности: Но если снять четвертую галку checkbox ("Выбрать все папки") – первые три галки checkbox (п.1, п2, п3) остаются (скриншот №2).

Вопрос: Как сделать, что бы при снятии четвертой галки checkbox ("Выбрать все папки") – первые три галки checkbox (п.1, п2, п3) тоже снимались.

P.S. предложения по улучшению кода приветствуются.


1. введите сюда описание изображения 2. введите сюда описание изображения

chech.py

import sys, os
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
from PyQt5.QtWidgets import (QWidget, QCheckBox, QMessageBox, )
from PyQt5.QtCore import (pyqtSlot, )

class MessageBox(QtWidgets.QMessageBox, QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Внимание!")
        self.setIcon(self.Critical)
        self.addButton(QtWidgets.QPushButton('Удалить'), QtWidgets.QMessageBox.YesRole)
        self.addButton(QtWidgets.QPushButton('Отмена'), QtWidgets.QMessageBox.NoRole)
        self.addCheckBox(self)

        currentClick = self.exec_()
        if currentClick == 0:
            print(' нажата кнопка = Удалить')
            print()

            if self.check1.isChecked() == False and \
               self.check2.isChecked() == False and \
               self.check3.isChecked() == False:
               self.not_del()
            else:
                if self.check1.isChecked() == True:
                    print(' значение CheckBox (1. ) =', self.check1.isChecked())
                    self.del_Doc()

                if self.check2.isChecked() == True:
                    print(' значение CheckBox (2. ) =', self.check2.isChecked())
                    self.del_Otv()

                if self.check3.isChecked() == True:
                    print(' значение CheckBox (3. ) =', self.check3.isChecked())
                    self.del_Im()
            self.message()
        if currentClick == 1:
            print(' нажата кнопка = Отмена')

    def addCheckBox(self, parentItem):
        self.l = QtWidgets.QVBoxLayout()
        lb1 = QtWidgets.QLabel("Файлы удалятся безвозвратно. \n              Вы уверены?", self)
        lb1.setGeometry(60, 15, 300, 40)
        lb2 = QtWidgets.QLabel('Следующие данные будут удалены:', self)
        lb2.setGeometry(20, 60, 350, 20)

        self._toggle = True
        self.check1 = QCheckBox('1.', self)
        self.check1.setGeometry(20, 85, 200, 20)
        self.check1.setChecked(self._toggle)

        self.check2 = QCheckBox('2.', self)
        self.check2.setGeometry(20, 105, 200, 20)
        self.check2.setChecked(self._toggle)

        self.check3 = QCheckBox('3.', self)
        self.check3.setGeometry(20, 125, 200, 20)
        self.check3.setChecked(self._toggle)

        self.check = QCheckBox('Выбрать все папки', self)
        self.check.setGeometry(20, 155, 200, 20)
        self.check.setChecked(self._toggle)

        self.check1.clicked.connect(self.chec_toggle)
        self.check2.clicked.connect(self.chec_toggle)
        self.check3.clicked.connect(self.chec_toggle)
        self.check.clicked.connect(self.chec_toggle)
        self.setLayout(self.l)

    @pyqtSlot()
    def chec_toggle(self):
        if self.sender() == self.check:
            if self._toggle == True:
                self.check1.setChecked(self._toggle)
                self.check2.setChecked(self._toggle)
                self.check3.setChecked(self._toggle)
            else:
                self.check1.setChecked(not self._toggle)
                self.check2.setChecked(not self._toggle)
                self.check3.setChecked(not self._toggle)
                self.check.setChecked(not self._toggle)

        elif self.sender() in (self.check1, self.check2, self.check3):
            self.check.setChecked(not self._toggle)

    def del_Doc(self): pass
    def del_Otv(self): pass
    def del_Im(self): pass

    def not_del(self):
        msgBox = QMessageBox(self)
        msgBox.setIcon(QMessageBox.Information)
        msgBox.setWindowTitle('Внимание!')
        msgBox.setText("   Ни одна папка не выбрана!   ")
        msgBox.exec_()

    def message(self):
        msgBox0 = QMessageBox(self)
        msgBox0.setIcon(QMessageBox.Information)
        msgBox0.setText('Операция очистки завершена.  ')
        msgBox0.exec_()

    def event(self, e):
        result = QtWidgets.QMessageBox.event(self, e)
        self.setMinimumWidth(0)
        self.setMaximumWidth(16777215)
        self.setMinimumHeight(0)
        self.setMaximumHeight(16777215)
        self.setSizePolicy(
            QtWidgets.QSizePolicy.Expanding,
            QtWidgets.QSizePolicy.Expanding
        )
        self.resize(250, 230)
        return result

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ex = MessageBox()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Sorry, мне тяжело помочь вам с вашим кодом. Возможное решение может выглядеть примерно так:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *


class Custom_QGroupBox(QtWidgets.QGroupBox):
    checkAllIfAny = True
    
    def __init__(self, *args, **kwargs):
        super(Custom_QGroupBox, self).__init__(*args, **kwargs)
        self.setCheckable(True)
        self.checkBoxes = []
        self.toggled.connect(self.toggleCheckBoxes)

    def addCheckBox(self, cb):
        self.checkBoxes.append(cb)
        cb.toggled.connect(self.update)
        cb.destroyed.connect(lambda: self.removeCheckBox(cb))

    def removeCheckBox(self, cb):
        try:
            self.checkBoxes.remove(cb)
            cb.toggled.disconnect(self.update)
        except:
            pass

    def allStates(self):
        return [cb.isChecked() for cb in self.checkBoxes]

    def toggleCheckBoxes(self):
        if self.checkAllIfAny:
            state = not all(self.allStates())
        else:
            state = not any(self.allStates())

        for widget in self.children():
            if not widget.isWidgetType():
                continue
            if not widget.testAttribute(QtCore.Qt.WA_ForceDisabled):
                # восстановить включенное состояние, чтобы переопределить 
                # поведение setChecked(False) по умолчанию; 
                # предыдущие явные вызовы setEnabled(False) для целевого виджета 
                # будут игнорироваться
                widget.setEnabled(True)
                if widget in self.checkBoxes:
                    widget.setChecked(state)

    def paintEvent(self, event):
        opt = QtWidgets.QStyleOptionGroupBox()
        self.initStyleOption(opt)
        states = self.allStates()
        if all(states):
            # force the "checked" state
            opt.state |= QtWidgets.QStyle.State_On
            opt.state &= ~QtWidgets.QStyle.State_Off
        else:
            # force the "not checked" state
            opt.state &= ~QtWidgets.QStyle.State_On
            if any(states):
                # force the "not unchecked" state and set the tristate mode
                opt.state &= ~QtWidgets.QStyle.State_Off
                opt.state |= QtWidgets.QStyle.State_NoChange
            else:
                # force the "unchecked" state
                opt.state |= QtWidgets.QStyle.State_Off
        painter = QtWidgets.QStylePainter(self)
        painter.drawComplexControl(QtWidgets.QStyle.CC_GroupBox, opt)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        
        self.groupBox = Custom_QGroupBox('Все папки')
        layout = QtWidgets.QGridLayout(self.groupBox)
        num = 0
        for c in range(1):
            for r in range(3):
                num += 1
                cb = QtWidgets.QCheckBox(f' {num}.')
                self.groupBox.addCheckBox(cb)
                layout.addWidget(cb, r, c)

        self.toolButton = QtWidgets.QToolButton()
        self.toolButton.setIcon(QtGui.QIcon('head3.png'))
        self.toolButton.setAutoRaise(True)
        self.toolButton.setIconSize(QtCore.QSize(70, 70))
        self.toolButton.setStyleSheet(
            'background-color: green; border-radius: 35px;')
            
        label_1 = QLabel("Файлы удалятся безвозвратно. Вы уверены?")
        label_1.setWordWrap(True)
        label_2 = QLabel('Следующие данные будут удалены:')
        
        self.buttonDelete = QPushButton('Удалить')
        self.buttonCancel = QPushButton('Отмена')
        layoutH = QHBoxLayout()
        layoutH.addStretch(1)
        layoutH.addWidget(self.buttonDelete)
        layoutH.addWidget(self.buttonCancel)

        main_layout = QtWidgets.QGridLayout(self)
        main_layout.addWidget(self.toolButton, 1, 1)
        main_layout.addWidget(label_1, 1, 2)
        main_layout.addWidget(label_2, 2, 1, 1, 2)
        main_layout.addWidget(self.groupBox, 3, 1, 1, 2)
        main_layout.addLayout(layoutH, 4, 1, 1, 2)
        
        main_layout.setRowStretch(0, 1)
        main_layout.setRowStretch(5, 1)
        main_layout.setColumnStretch(0, 1)
        main_layout.setColumnStretch(3, 1)
            

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
    w = MainWindow()
    w.resize(370, 300)
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

→ Ссылка