Why can't I set a tristate QCheckBox to Qt.PartiallyChecked and have the QCheckBox display a partial check?

2.3k views Asked by At

I'm using python3 and PyQt5.

The example below has three QPushButtons and a QCheckBox with setTristate to true. I can click directly on the checkbox and it will cycle through the three states just fine.

THE PROBLEM: If I attempt to set the state value from the neighboring buttons, it only gives me checked or unchecked. It's maddening.

#!/usr/bin/env python3


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


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        hbox = QHBoxLayout(self)
        
        
        qb1=QPushButton("Uncheck it")
        qb2=QPushButton("Partial Check it")
        qb3=QPushButton("Check it reals")
        qb1.clicked.connect(self.uncheck_it) 
        qb2.clicked.connect(self.partial_check_it) 
        qb3.clicked.connect(self.check_it) 
        
        
        
        self.qch=QCheckBox("Chonk") 
        self.qch.stateChanged.connect(self.chonker) 
        self.qch.setTristate(True) 


        hbox.addWidget(self.qch)
        hbox.addWidget(qb1)
        hbox.addWidget(qb2)
        hbox.addWidget(qb3)
        self.setLayout(hbox)

        self.move(300, 200)
        self.setWindowTitle('Choooo')
        self.show()

    def chonker(self):
        print("chonker", self.sender().text(),self.sender().isChecked())
        
    def uncheck_it(self):
        self.qch.setChecked(Qt.Unchecked)
        print ("Uncheck it")
    def partial_check_it(self):
        self.qch.setChecked(Qt.PartiallyChecked)
        print ("Partial check it")
    def check_it(self):
        self.qch.setChecked(Qt.Checked)
        print ("Check it")


    

def main():
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

2

There are 2 answers

0
eyllanesc On

The setChecked() method only changes to 2 states: checked or unchecked. If you want to change to all 3 states then you must use setCheckState() method:

def uncheck_it(self):
    self.qch.setCheckState(Qt.Unchecked)
    print("Uncheck it")

def partial_check_it(self):
    self.qch.setCheckState(Qt.PartiallyChecked)
    print("Partial check it")

def check_it(self):
    self.qch.setCheckState(Qt.Checked)
    print("Check it")
2
snaxxus On

Thanks user eyllanesc!

In the code below used the alternate functions that are correct for the tri-state checkbox.

replaced function setChecked with function setCheckState. replaced function isChecked with the function checkState that actually returns the tristate value.

This one works!

#!/usr/bin/env python3


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


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        hbox = QHBoxLayout(self)
        
        
        qb1=QPushButton("Uncheck it")
        qb2=QPushButton("Partial Check it")
        qb3=QPushButton("Check it reals")
        qb1.clicked.connect(self.uncheck_it) 
        qb2.clicked.connect(self.partial_check_it) 
        qb3.clicked.connect(self.check_it) 
        
        
        
        self.qch=QCheckBox("Chonk") 
        self.qch.stateChanged.connect(self.chonker) 
        self.qch.setTristate(True) 


        hbox.addWidget(self.qch)
        hbox.addWidget(qb1)
        hbox.addWidget(qb2)
        hbox.addWidget(qb3)
        self.setLayout(hbox)

        self.move(300, 200)
        self.setWindowTitle('Choooo')
        self.show()

    def chonker(self):
        print("chonker", self.sender().text(),self.sender().checkState())
        
    def uncheck_it(self):
        self.qch.setCheckState(Qt.Unchecked)
        print ("Uncheck it")
    def partial_check_it(self):
        self.qch.setCheckState(Qt.PartiallyChecked)
        print ("Partial check it")
    def check_it(self):
        self.qch.setCheckState(Qt.Checked)
        print ("Check it")


    

def main():
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()