QCheckBox

Toggleable checkable widget
Heads up! You've already completed this tutorial.

A checkbox is a square-shaped widget used in graphical user interfaces (GUI) to provide users with a way to enable or disable options, or to allow users to enable or disable certain features of the app. Checkboxes usually have an adjacent label, indicating what the checkbox represents.

Checkboxes are usually used to represent boolean state, being either checked (on) or unchecked (off). However, you can also have tri-state checkboxes with a third indeterminate state. In this tutorial, you'll learn how to create and customize checkboxes in your own applications, using the QCheckBox class.

Creating Checkbox Widgets With QCheckBox

The QCheckBox class represents a checkbox widget. A checkbox is an option widget that can be switched on (checked) or off (unchecked) by the user. This widget is common in settings or preferences dialogs where the user fine-tunes an application's configuration.

Checkboxes typically have a square shape looking like a checkbox on a paper form. We can click the box to switch it on and click it again to switch it off. When checked a cross or checkmark symbol will appear in the box. When a checkbox is unchecked, it will appear as an empty square.

If you're using PyQt or PySide to create GUI applications in Python, then you can add checkboxes to your application with the QCheckBox class. This class provides two different constructors that we can use to create checkboxes:

Constructor Description
QCheckBox(parent: QWidget = None) Constructs a checkbox with an optional parent widget but without an associated text
QCheckBox(text: str, parent: QWidget = None) Constructs a checkbox with an associated description text and an optional parent widget

To illustrate how to use the above constructors, let's get into our first example:

python
import sys

from PyQt6.QtWidgets import (
    QApplication,
    QCheckBox,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        # Checkbox with no label
        noTextCkBox = QCheckBox()
        # Checkbox with a text label
        textCkBox = QCheckBox(text="Option")
        layout = QVBoxLayout()
        layout.addWidget(noTextCkBox)
        layout.addWidget(textCkBox)
        self.setLayout(layout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())
python
import sys

from PySide6.QtWidgets import (
    QApplication,
    QCheckBox,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        # Checkbox with no label
        noTextCkBox = QCheckBox()
        # Checkbox with a text label
        textCkBox = QCheckBox(text="Option")
        layout = QVBoxLayout()
        layout.addWidget(noTextCkBox)
        layout.addWidget(textCkBox)
        self.setLayout(layout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

In this example, we import QCheckBox from the QtWidgets module. We create two QCheckBox instances in the __init__ method of the Window class. The first is created using the constructor that does not require a text label.

Both constructors take an optional parent widget, but since we are adding the checkbox widgets to a layout, we don't need to pass a parent when contructing them.

Next up, we use the second constructor of QCheckBox to create another checkbox, this time with descriptive label. The text will display on the right of the checkbox. The text is a regular Python string. This label would typically be used to describe the option to be enabled or disabled, but here is just "Option".

Save this code to a .py file and run it. You'll get a window that looks something like this:

QCheckBox constructors

As expected, the first checkbox has no associated text. It's just a square box on the window. This isn't too helpful, because it doesn't provide any information to your users. However, it can be useful when creating an array of checkboxes laid out to present some data in a table or a list.

The second checkbox on the window looks more familiar -- it has an associated text.

Both checkboxes are fully functional. We can check and uncheck them by clicking on them or -- in the case of the second example -- on the label. However, the checkboxes don't do any action yet, they just change their internal state from checked to unchecked and the other way around. To give a checkbox purpose we need to check the state and take action accordingly ourselves.

In most UIs checkboxes typically don't trigger external actions when toggled. Use buttons to launch or trigger things.

Normal checkboxes have two internal states Checked and Unchecked, while tri-state checkboxes add a third PartiallyChecked state. Next we'll look at how to check and set these states on both two-state and tri-state checkboxes.

Getting and Setting Checkbox state

The most important property of a checkbox is its internal state. This holds whether the checkbox is checked or not. By checking this property, you can take appropriate action in your application.

There are two main methods for checking the checkbox internal state -- isChecked() and checkState(). The possible values returned for a two-state checkbox are shown below:

Methods Behavior
isChecked() Will return True if checkbox is checked, False if it is unchecked.
checkState() In two-state checkboxes this will return either Checked and Unchecked.

Consider the following example:

python
import sys

from PyQt6.QtWidgets import (
    QApplication,
    QCheckBox,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.checkBox = QCheckBox(text="Unchecked")
        layout = QVBoxLayout()
        layout.addWidget(self.checkBox)
        self.setLayout(layout)
        self.checkBox.stateChanged.connect(self.onStateChanged)

    def onStateChanged(self):
        if self.checkBox.isChecked():
            self.checkBox.setText("Checked")
        else:
            self.checkBox.setText("Unchecked")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())
python
import sys

from PySide6.QtWidgets import (
    QApplication,
    QCheckBox,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.checkBox = QCheckBox(text="Unchecked")
        layout = QVBoxLayout()
        layout.addWidget(self.checkBox)
        self.setLayout(layout)
        self.checkBox.stateChanged.connect(self.onStateChanged)

    def onStateChanged(self):
        if self.checkBox.isChecked():
            self.checkBox.setText("Checked")
        else:
            self.checkBox.setText("Unchecked")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

In this example, we first create a QCheckBox instance with the text "Click me!" on it. In this case, we're defining a two-state checkbox, which represents the default behavior of this widget.

Then we create the app's layout and add the checkbox. Finally, we connect the stateChanged() signal with the onStateChanged() slot or method. This signal is emitted whenever we click the checkbox, and the onStateChanged() method is automatically called.

You can use the stateChanged() signal to trigger something to happen each time the checkbox changes its state. To connect the stateChanged() signal to a slot, you use the standard syntax:

python
checkbox.<signal>.connect(<method>)

In this construct, checkbox is the QCheckBox object we need to connect to a given slot. The <signal> name is stateChanged. Finally, <method> represents the target slot or method we want to connect the signal.

The onStateChanged() method uses isChecked() to determine the current state of our checkbox. This method returns True if the checkbox is checked and False if it's unchecked. The checkbox text changes alternatively from Checked to Unchecked depending on the result of this condition:

Two-state checkbox

Whenever you click the checkbox on this window, the text changes from Checked to Unchecked alternatively.

It's usually not a good idea to change a checkbox label with the state as it's confusing. Does the "Unchecked" label next to a unchecked checkbox mean checked or unchecked?

We could have used checkState() to determine the current state of our checkbox in the above example. However, using isChecked() feels more natural when working with two-state checkboxes.

When we are working with tri-state checkboxes, checkState() is our only option. We'll see how to work with checkState() in the next section.

Building and Working With Tri-State Checkboxes

In addition to regular two-state checkboxes, you can optionally create tri-state checkboxes. This type of checkbox comes in handy when we want to give our user the option to set the checkbox in an intermediate state known as a partially checked state. This state means that the checkbox is neither checked nor unchecked.

Tri-state checkboxes are typically used to represent groups of other checkboxes, allowing them to all be turned on or off in one go. The partially checked state then indicates that some of the children are on and some are off.

When using tri-state checkboxes, the isChecked() and checkState() methods return the following values --

Methods Behavior
isChecked() Will return True if checkbox is checked or partially checked, False if it is unchecked.
checkState() In three-state checkboxes this will return either Checked, Unchecked or PartiallyChecked .

The QCheckBox class has a Boolean tristate property that indicates whether the checkbox is tri-state. This property defaults to False. If we set it to True, we turn our checkbox into a tri-state checkbox. To change the value of tristate, you need to use the setTristate() with a boolean value as an argument.

You can also turn a checkbox tri-state by setting a partially checked state on it, using .setState(Qt.CheckState.PartiallyChecked).

Consider the following example:

python
import sys

from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (
    QApplication,
    QCheckBox,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.triStateCheckBox = QCheckBox(text="Unchecked")
        self.triStateCheckBox.setTristate(True)
        layout = QVBoxLayout()
        layout.addWidget(self.triStateCheckBox)
        self.setLayout(layout)
        self.triStateCheckBox.stateChanged.connect(self.onStateChanged)

    def onStateChanged(self):
        state = self.triStateCheckBox.checkState()
        if state == Qt.CheckState.Checked:
            self.triStateCheckBox.setText("Checked")
        elif state == Qt.CheckState.PartiallyChecked:
            self.triStateCheckBox.setText("Partially checked")
        else:
            self.triStateCheckBox.setText("Unchecked")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())
python
import sys

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
    QApplication,
    QCheckBox,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.triStateCheckBox = QCheckBox(text="Unchecked")
        self.triStateCheckBox.setTristate(True)
        layout = QVBoxLayout()
        layout.addWidget(self.triStateCheckBox)
        self.setLayout(layout)
        self.triStateCheckBox.stateChanged.connect(self.onStateChanged)

    def onStateChanged(self):
        state = self.triStateCheckBox.checkState()
        if state == Qt.CheckState.Checked:
            self.triStateCheckBox.setText("Checked")
        elif state == Qt.CheckState.PartiallyChecked:
            self.triStateCheckBox.setText("Partially checked")
        else:
            self.triStateCheckBox.setText("Unchecked")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

In this example, we create a regular checkbox using the QCheckBox() constructor. To set this checkbox as tri-state, you call .setTristate() with True as an argument. From now on, our checkbox will have three states represented by the following values:

Constant Value Description
Qt.CheckState.Unchecked 0 The checkbox is unchecked.
Qt.CheckState.PartiallyChecked 1 The checkbox is partially checked.
Qt.CheckState.Checked 2 The checkbox is checked.

In tri-state checkboxes, the isChecked() method will return True whether the checkbox is checked or partially checked, and False if it is unchecked.

If you want to distinguish between checked and partially checked states, you need to use checkState() directly. Calling checkState() returns one of the constants in the above table, representing the current state of the checkbox.

Our onStateChanged() method is connected to the stateChanged signal of the checkbox. In this method, we get the current state by calling checkState() on the checkbox and storing the result in the variable state. We then check the value of this variable against the different states and take action accordingly. In this example, we alternatively change the checkbox text to reflect its state.

Here's how this example works in practice:

Tri-state checkbox

When you click the checkbox, its text changes from Unchecked to Partially checked and finally to Checked. These are the three possible states of this kind of checkbox.

While we used the checkState() method above, the stateChanged signal actually sends the current state, as an integer value, to the slot. We can map that into the correct state in the method directly by passing it to Qt.CheckState. For example.

python
    def onStateChanged(self, state):
        state = Qt.CheckState(state)
        if state == Qt.CheckState.Checked:
            self.triStateCheckBox.setText("Checked")
        elif state == Qt.CheckState.PartiallyChecked:
            self.triStateCheckBox.setText("Partially checked")
        else:
            self.triStateCheckBox.setText("Unchecked")

In this alternative implementation of onStateChanged(), we receive a state argument that we map to a Qt.CheckState object. The rest of the code remains the same.

The mapping step is only required in PyQt6. In both PyQt5, PySide2, and PySide6 this is done automatically.

It's up to you which implementation to use in your code.

Using Checkboxes in Practice

We can use checkbox widgets to provide a clean and user-friendly way to enable or disable options in a GUI app. Checkboxes are useful when building preferences or setting dialogs where the users can customize our applications. For example, say that you're making a text editor and you want to allow the user to customize a few features like:

  • Show word count
  • Auto pair brackets
  • Show minimap

Checkbox options shouldn't usually be mutually exclusive. If you have mutually exclusive options, consider using the QRadioButton class instead.

In this case, you can use a checkbox for each of these options like in the following code:

python
import sys

from PyQt6.QtWidgets import (
    QApplication,
    QCheckBox,
    QLabel,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.wordCountCkBox = QCheckBox(text="Show word count", parent=self)
        self.bracketsCkBox = QCheckBox(text="Auto pair brackets", parent=self)
        self.minimapCkBox = QCheckBox(text="Show minimap", parent=self)
        self.selectionLabel = QLabel(text="No selection yet", parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.wordCountCkBox)
        layout.addWidget(self.bracketsCkBox)
        layout.addWidget(self.minimapCkBox)
        layout.addWidget(self.selectionLabel)
        self.setLayout(layout)
        self.wordCountCkBox.stateChanged.connect(self.onStateChanged)
        self.bracketsCkBox.stateChanged.connect(self.onStateChanged)
        self.minimapCkBox.stateChanged.connect(self.onStateChanged)

    def onStateChanged(self):
        selection = "You've selected:\n"
        if self.wordCountCkBox.isChecked():
            selection += "- Word count\n"
        if self.bracketsCkBox.isChecked():
            selection += "- Auto pair brackets\n"
        if self.minimapCkBox.isChecked():
            selection += "- Show minimap\n"
        self.selectionLabel.setText(selection)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())
python
import sys

from PySide6.QtWidgets import (
    QApplication,
    QCheckBox,
    QLabel,
    QVBoxLayout,
    QWidget,
)

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.wordCountCkBox = QCheckBox(text="Show word count", parent=self)
        self.bracketsCkBox = QCheckBox(text="Auto pair brackets", parent=self)
        self.minimapCkBox = QCheckBox(text="Show minimap", parent=self)
        self.selectionLabel = QLabel(text="No selection yet", parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.wordCountCkBox)
        layout.addWidget(self.bracketsCkBox)
        layout.addWidget(self.minimapCkBox)
        layout.addWidget(self.selectionLabel)
        self.setLayout(layout)
        self.wordCountCkBox.stateChanged.connect(self.onStateChanged)
        self.bracketsCkBox.stateChanged.connect(self.onStateChanged)
        self.minimapCkBox.stateChanged.connect(self.onStateChanged)

    def onStateChanged(self):
        selection = "You've selected:\n"
        if self.wordCountCkBox.isChecked():
            selection += "- Word count\n"
        if self.bracketsCkBox.isChecked():
            selection += "- Auto pair brackets\n"
        if self.minimapCkBox.isChecked():
            selection += "- Show minimap\n"
        self.selectionLabel.setText(selection)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

In this example, we create three checkboxes, one per option. We also create a label object to show the user's selections. If you run this application, then you'll get the following behavior:

Checkboxes for text editor settings

This dialog shows the three required options for your text editor. Of course, this dialog doesn't look like a fully functional setting or preferences dialog. It intends to show how you can use checkboxes to provide non-exclusive options to your users. Note that you can select any combination of options.

Setting Other Properties of QCheckBox

Up to this point, we've learned how to create two-state and tri-state checkboxes in your GUI applications. We've also learned how to make our checkboxes perform actions in response to state changes by connecting the stateChanged signals with concrete methods known as slots.

In this section, we'll learn about other useful features of QCheckBox, including the text and icon properties shown below:

Property Description Getter Method Setter Method
text Holds the text shown on the button text() setText()
icon Holds the icon shown on the button icon() setIcon()

As its name suggests, the text property controls the current text associated with a checkbox. You can use the setText() method to change this property and text() to retrieve its current value if needed. In previous sections, you used setText() to change the text of a checkbox. So, let's focus on how to work with icons.

Here's an example of a checkbox representing a traffic light in which each state will have its own associated icon:

python
import sys

from PyQt6.QtCore import Qt
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication, QCheckBox, QVBoxLayout, QWidget

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.lightCkBox = QCheckBox(parent=self)
        self.lightCkBox.setTristate(True)
        self.lightCkBox.setIcon(QIcon("icons/red.png"))
        layout = QVBoxLayout()
        layout.addWidget(self.lightCkBox)
        self.setLayout(layout)
        self.lightCkBox.stateChanged.connect(self.onStateChanged)

    def onStateChanged(self, state):
        state = Qt.CheckState(state)
        if state == Qt.CheckState.Checked:
            self.lightCkBox.setIcon(QIcon("icons/green.png"))
        elif state == Qt.CheckState.PartiallyChecked:
            self.lightCkBox.setIcon(QIcon("icons/yellow.png"))
        else:
            self.lightCkBox.setIcon(QIcon("icons/red.png"))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())
python
import sys

from PySide6.QtCore import Qt
from PySide6.QtGui import QIcon
from PySide6.QtWidgets import QApplication, QCheckBox, QVBoxLayout, QWidget

class Window(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.lightCkBox = QCheckBox(parent=self)
        self.lightCkBox.setTristate(True)
        self.lightCkBox.setIcon(QIcon("icons/red.png"))
        layout = QVBoxLayout()
        layout.addWidget(self.lightCkBox)
        self.setLayout(layout)
        self.lightCkBox.stateChanged.connect(self.onStateChanged)

    def onStateChanged(self, state):
        state = Qt.CheckState(state)
        if state == Qt.CheckState.Checked:
            self.lightCkBox.setIcon(QIcon("icons/green.png"))
        elif state == Qt.CheckState.PartiallyChecked:
            self.lightCkBox.setIcon(QIcon("icons/yellow.png"))
        else:
            self.lightCkBox.setIcon(QIcon("icons/red.png"))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

In this example, we use the setIcon() method to change the icon associated with the checkbox according to its current state. Go ahead and run the app! You'll get a window like the following:

Checkbox with icons

In this example, the red light is associated with the unchecked state, the yellow light is linked to the partially checked state, and the green light is associated with the checked state.

Using icons like in this example is something rare with checkbox widgets. You'll typically use descriptive text. But it's good to know the capability is there for when you need it.

Conclusion

Checkboxes are useful widgets in any GUI application. They allow us to give our users a clean way to enable or disable options in our applications. They are commonly used in dialogs and preferences windows to allow enabling and disabling of application features or configuring behavior.

In this tutorial, you've learned how to create, use, and customize checkboxes while building a GUI application with PyQt.

Create GUI Applications with Python & Qt6 by Martin Fitzpatrick — (PySide6 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!

More info Get the book

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

QCheckBox was written by Leo Well .