Top.Mail.Ru

Qt. QML CheckBox. Кастомизация, свойства, примеры стилей.

Всех приветствую, сегодня продолжим обзор наиболее базовых элементов QML - на очереди стоит CheckBox. И снова большинство вопросов связаны с кастомизацией стиля, поэтому обязательно рассмотрим пару-тройку конкретных вариантов реализации.

QML CheckBox. Базовые операции.

Начнем по традиции с пустого Qt Quick проекта, в который добавим исключительно то, что будем рассматривать, то есть CheckBox посередине окна 👍

QML default checkbox

Все изменения сегодня будут осуществлены в main.qml:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
    width: 320
    height: 240
    visible: true
    title: qsTr("QML CheckBox Review ")

    CheckBox {
        id: testCheckBox
        anchors.centerIn: parent

        text: qsTr("To check or not to check...")
    }
}

В принципе, обычно взаимодействие с CheckBox заключается в проверке свойства checkState. Возможные значения зависят в свою очередь от свойства tristate. По умолчанию tristate = false, и checkState может принимать значения:

  • Qt.Unchecked
  • Qt.Checked

Если tristate = true, то спектр вариантов пополняется еще одним:

  • Qt.Unchecked
  • Qt.PartiallyChecked
  • Qt.Checked

Тут все просто и очевидно, но тем не менее небольшой пример. Добавим текстовое поле под CheckBox для отображения его состояния:

Window {
    width: 320
    height: 240
    visible: true
    title: qsTr("QML CheckBox Review ")

    CheckBox {
        id: testCheckBox
        anchors.centerIn: parent

        text: qsTr("To check or not to check...")

        onCheckStateChanged: {
            switch (checkState) {
                case Qt.Unchecked:
                    testCheckBoxState.text = "I'm unchecked";
                    break;

                case Qt.PartiallyChecked:
                    testCheckBoxState.text = "I'm partially checked";
                    break;

                case Qt.Checked:
                    testCheckBoxState.text = "I'm checked";
                    break;

                default:
                    break;
            }
        }
    }

    Text {
        id: testCheckBoxState
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: testCheckBox.bottom
        anchors.topMargin: 10

        text: qsTr("State")
    }
}
States

Об изменении checkState мы узнаем из обработчика onCheckStateChanged. Без него мы могли спокойно обойтись, просто забросив в Text:

Text {
	id: testCheckBoxState
	anchors.horizontalCenter: parent.horizontalCenter
	anchors.top: testCheckBox.bottom
	anchors.topMargin: 10

	text: qsTr("State") + " " + testCheckBox.checkState
}

Но ладно, оставим обработчик и изменим tristate:

CheckBox {
	id: testCheckBox
	anchors.centerIn: parent
	tristate: true
// ...............

Результат закономерен:

Tristate example

По сути это скорее справочная информация, поскольку все максимально просто. Так что рассмотрим еще один, менее распространенный, но тем не менее часто использующийся вариант, который, в общем-то, неплохо разобран и в официальной документации.

QML CheckBox. Иерархическая структура.

Кстати здесь будет уже понятно, зачем вообще нужно состояние Qt.PartiallyChecked. Итак, добавим три CheckBox и элемент ButtonGroup. При этом свяжем их друг с другом при помощи свойства ButtonGroup.group каждого из CheckBox:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
    width: 320
    height: 240
    visible: true
    title: qsTr("QML CheckBox Review ")

    Column {
        id: mainColumn

        ButtonGroup {
            id: primaryGroup
            exclusive: false
        }

        CheckBox {
            text: qsTr("CheckBox 1")
            ButtonGroup.group: primaryGroup
        }

        CheckBox {
            text: qsTr("CheckBox 2")
            ButtonGroup.group: primaryGroup
        }

        CheckBox {
            text: qsTr("CheckBox 3")
            ButtonGroup.group: primaryGroup
        }
    }

    Text {
        id: primaryGroupState
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: mainColumn.bottom
        anchors.topMargin: 10

        text: qsTr("State") + " " + primaryGroup.checkState
    }
}

В Text будем выводить состояние ButtonGroup через primaryGroup.checkState. В чем смысл содеянного... А смысл в том, что состояние ButtonGroup будет определяться состояниями всех, добавленных к ней элементов. То есть в данном случае это CheckBox'ы. При этом взаимосвязь следующая:

  • Если все CheckBox - unchecked, то и primaryGroup - unchecked.
  • Если все CheckBox - checked, то primaryGroup - checked.
  • Если часть из CheckBox (но не все) - checked, primaryGroup - partially checked.

Вот такая логика. Проверяем: