Qt 5.7 QML Почему мои привязки свойств CheckBox исчезают?

У меня есть простой список CheckBoxes, по одному на каждый день недели. Они зависят от значения days, целого числа, использующего маску, по 1 биту на каждое CheckBox.

Назначение на days как кнопкой "очистить все", так и кнопкой "установить все" работает и они обновляются. Однако после щелчка по любому из полей они больше не реагируют на изменения в зависимом свойстве days.

Почему это? Они как-то развязываются. Если да, то должен ли я повторно связывать их вручную, и если да, то почему?

Вот код,

import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3

ApplicationWindow
{
    visible: true
    width: 800
    height: 400

    property int days: 0

    ColumnLayout
    {
        Repeater
        {
            model: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
            CheckBox
            {
                text: modelData
                checked: (days & (1<<index)) != false
                onClicked:
                {
                    if (checked) days |= (1<<index);
                    else days &= ~(1<<index);
                }

            }
        }

        Button 
        {
            text: "clear all"
            onClicked: days = 0
        }

        Button 
        {
            text: "set all"
            onClicked: days = 127
        }
    }
}

который выглядит так:

введите описание изображения здесь

Чтобы воспроизвести проблему, сначала нажмите «установить все» и «очистить все». затем установите некоторые флажки. Затем снова нажмите «установить все» и «очистить все». Вы увидите, что флажки, которые вы отметили, больше не затрагиваются.

Благодарю.


person jkj yuio    schedule 05.08.2016    source источник


Ответы (2)


Когда вы вручную устанавливаете флажок, свойство checked переназначается жестко запрограммированному true вместо исходного выражения: (days & (1<<index)) != false. Аналогичным образом снятие флажка вручную приводит к тому, что свойство checked становится жестко заданным false.

Исправление состоит в том, чтобы просто перепривязать свойство checked с помощью Qt.binding . Я почистил ваш javascript и исправил вашу ошибку. Добро пожаловать.

    Repeater
    {
        model: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
        CheckBox
        {
            function isChecked() {
                return ((days & (1 << index)) != 0);
            }

            text: modelData
            checked: isChecked()
            onClicked:
            {
                if (checked) {
                    days |= (1<<index);
                }
                else {
                    days &= ~(1<<index);
                }

                // now rebind the item's checked property
                checked = Qt.binding(isChecked);

            }
        }
    }
person selbie    schedule 06.08.2016
comment
Большое спасибо! Ваш ответ работает удовольствие. Я не осознавал, что присваивание days привело к нарушению зависимости checked. Спасибо за объяснение. - person jkj yuio; 06.08.2016
comment
Присвоение days не приводит к нарушению свойства checked. Фактический щелчок пользователя по флажку приводит к его поломке. Подумайте об этом так. Прямо перед вызовом onClicked Qt вызывает checked=true;, тем самым переопределяя ваше условное выражение. - person selbie; 07.08.2016
comment
Да, ты прав, конечно. это делается фактическим щелчком. Спасибо за разъяснения. - person jkj yuio; 08.08.2016

ОП здесь.

Ответ Селби совершенно правильный. Но я хотел бы опубликовать вариант, который я предпочитаю.

Я пришел к выводу, что CheckBoxes не работают в QT. Это потому, что вы захотите связать их с вашей моделью данных. и вам тоже захочется на них нажимать (иначе какой в ​​этом смысл). Нажатие на них разрывает связь с моделью, поэтому ее нужно исправлять вручную (см. ответ Селби). Для меня это сломанный дизайн.

В моем варианте используется Binding, поэтому его не нужно восстанавливать каждый раз, когда вы нажимаете.

как это:

import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3

ApplicationWindow
{
    visible: true
    width: 800
    height: 400

    property int days: 0

    ColumnLayout
    {
        Repeater
        {
            model: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
            CheckBox
            {
                text: modelData
                Binding on checked { value: (days & (1 << index)) != 0 }
                onClicked:
                {
                    if (checked) days |= (1<<index)
                    else days &= ~(1<<index)
                }
            }
        }

        Button 
        {
            text: "clear all"
            onClicked: days = 0
        }

        Button 
        {
            text: "set all"
            onClicked: days = 127
        }
    }
}

Публикация этого варианта на благо других.

person jkj yuio    schedule 08.08.2016