0

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()

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
snaxxus
  • 339
  • 2
  • 6

2 Answers2

4

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")
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
0

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()
snaxxus
  • 339
  • 2
  • 6
  • 2
    I don't understand why post a second "answer" that already covered my answer. I would understand a new answer if it gives another option or points out that some of the other answers have drawbacks. Maybe I'm wrong, could you explain? What advantages does your response bring to the site? – eyllanesc Oct 06 '20 at 17:40
  • I hadn't seen the previous one yet when I typed it. Didn't see the need to erase it. Thanks – snaxxus Oct 07 '20 at 15:07