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.

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

QML Checkbox список

Помним, что Qt.Unchecked соответствует 0, Qt.PartiallyChecked - 1, Qt.Checked - 2. На базе этого можно построить иерархическую структуру CheckBox'ов. Суть заключается в том, что добавляется некий "главный" CheckBox, и его состояние жестко связывается с состоянием ButtonGroup. При этом текущие три CheckBox'а свойством leftPadding немного смещаются правее, что визуально выглядит как некая иерархия:

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

        CheckBox {
            id: mainCheckBox
            text: qsTr("Main")
            checkState: primaryGroup.checkState
        }

        ButtonGroup {
            id: primaryGroup
            exclusive: false
            checkState: mainCheckBox.checkState
        }

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

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

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

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

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

Ну и, естественно, состояние mainCheckBox теперь меняется так же, как ранее мы разбирали для ButtonGroup. Результат получаем такой:

По аналогии можно сделать и трехуровневый список:

Код же будет такой:

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

        CheckBox {
            id: mainCheckBox
            text: qsTr("Main")
            checkState: primaryGroup.checkState
        }

        ButtonGroup {
            id: primaryGroup
            exclusive: false
            checkState: mainCheckBox.checkState
        }

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

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

        CheckBox {
            id: checkBox3
            text: qsTr("CheckBox 3")
            leftPadding: 20
            ButtonGroup.group: primaryGroup
            checkState: secondaryGroup.checkState
        }

        ButtonGroup {
            id: secondaryGroup
            exclusive: false
            checkState: checkBox3.checkState
        }

        CheckBox {
            text: qsTr("CheckBox 3.1")
            leftPadding: 40
            ButtonGroup.group: secondaryGroup
        }

        CheckBox {
            text: qsTr("CheckBox 3.2")
            leftPadding: 40
            ButtonGroup.group: secondaryGroup
        }
    }
}

Все, переходим к следующему подразделу.

QML CheckBox. Стили. Кастомизация.

Опять же, как и для многих QML компонентов, можно легко выделить несколько конкретных свойств, отвечающих за ту или иную часть CheckBox'а. В данном случае их три:

  • background
  • contentItem
  • indicator

Откатимся снова к первоначальному виду приложения и рассмотрим несколько вариантов кастомизации стиля на основе перечисленных свойств. На конкретных примерах будет более понятно, что и за что отвечает:

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...")

        background: Rectangle {
            color: "#C0C0C0"
        }

        contentItem: Text {
            color: "#800000";
            text: testCheckBox.text
            verticalAlignment: Text.AlignVCenter
            leftPadding: testCheckBox.indicator.width
        }

        indicator: Rectangle {
            color: testCheckBox.checked ? "#2E8B57" : "#3CB371"
            y: testCheckBox.height / 2 - height / 2
            implicitWidth: 25
            implicitHeight: 25
        }
    }
}
Стиль checkbox

Дизайн, очевидно, так себе ) Но тут смысл в том, чтобы разобраться, за что отвечают те или иные свойства и под себя уже сделать как душе угодно:

Пример CheckBox на QML

Для indicator можно добавить еще внутренний элемент, к примеру так:

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...")

        background: Rectangle {
            color: "transparent"
        }

        contentItem: Text {
            color: "#000000";
            text: testCheckBox.text
            verticalAlignment: Text.AlignVCenter
            leftPadding: testCheckBox.indicator.width
        }

        indicator: Rectangle {
            color: "#008080"
            y: testCheckBox.height / 2 - height / 2
            implicitWidth: 25
            implicitHeight: 25
            radius: 8

            Rectangle {
                color: "#E0FFFF"
                visible: testCheckBox.checked
                width: parent.width / 2
                height: parent.height / 2
                x: parent.width / 2 - width / 2
                y: parent.height / 2 - height / 2
                radius: 4
            }
        }
    }
}
QML 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 ")
    color: "#303035"

    CheckBox {
        id: testCheckBox
        anchors.centerIn: parent

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

        background: Rectangle {
            color: "transparent"
        }

        contentItem: Text {
            color: "#FFFFFF";
            text: testCheckBox.text
            verticalAlignment: Text.AlignVCenter
            leftPadding: testCheckBox.indicator.width
            font.pointSize: 9
        }

        indicator: Rectangle {
            y: testCheckBox.height / 2 - height / 2
            implicitWidth: 25
            implicitHeight: 25
            radius: 4
            border.color: "#800000"

            Rectangle {
                visible: testCheckBox.checked
                width: parent.width / 2
                height: parent.height / 2
                x: parent.width / 2 - width / 2
                y: parent.height / 2 - height / 2
                radius: 2
                color: testCheckBox.down ? "#CD5C5C" : "#B22222"
            }
        }
    }
}
Еще один пример checkbox

На этом заканчиваем сегодняшний обзор CheckBox, до связи!

Подписаться
Уведомление о
guest
0 комментариев
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x