Тип привязки: возможно ли прослушать временно переопределенную привязку? - PullRequest
1 голос
/ 27 февраля 2020

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

  1. Разработчик, использующий виджет, привязывает значение виджета к некоторому внешнему значению
  2. Во время выполнения значение виджета следует за любым внешним значением изменения через эту привязку
  3. Пользователь взаимодействует с виджетом, устанавливая свое собственное значение
  4. Через некоторое время внешнее значение обновляется
  5. В идеале значение виджета затем должно вернуться к привязке к внешнее значение

Точка 5 не представляется возможной при использовании только привязок. Вот пример, где 'textItem' является нашим воображаемым виджетом:

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    property real externalValue: (Math.random()* 50).toFixed(0)

    Timer {
        running: true
        repeat: true
        interval: 1000
        onTriggered: {
            // Simulate externalValue changes out of our control
            externalValue = (Math.random()* 50).toFixed(0)
        }
    }

    Component.onCompleted: {
        // Unknown external binding set by developer using textItem widget
        textItem.text = Qt.binding(function(){return externalValue})
    }

    Column {

        Text {
            id: textItem
            text: ""

            property real internalValue: (Math.random()* 50).toFixed(0)

            Binding on text {
                id: binding
                value: textItem.internalValue
                when: false
            }
        }

        Button {
            text: "Change Internal Value"
            onClicked: {
                textItem.internalValue = (Math.random()* 50).toFixed(0)
                binding.when = true
            }
        }
    }
}

Так что textItem.text слушает привязку externalValue, пока пользователь не взаимодействует с кнопкой, которая затем связывает textItem.text с пользовательским набором. внутренняя ценность. Предполагая, что textEdit является виджетом черного ящика, и у него нет понятия externalValue до его привязки во время выполнения, есть ли способ для textEdit внутренне прослушивать переопределенную привязку externalValue и восстановить ее (установив binding.when = false) в следующий раз что externalValue обновляется таймером?

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

1 Ответ

1 голос
/ 28 февраля 2020

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

Настоящая проблема здесь заключается в обнаружении изменения внешнего значения, в моем решении я использую Timer для этого, но ваши требования требуют, чтобы внешняя ценность снова изменилась. Так как вы внешне привязываетесь к свойству text, а также перекрываете привязку к text, вы временно теряете сигналы изменения из внешней привязки, поэтому не можете отменить временную привязку.

Если у вас есть контроль над виджетом Я хотел бы реализовать свойство, которое должно быть установлено внешне и внутренне присваивать это значение туда, где оно должно go. Это дает вам возможность получать изменения и, например, останавливать tempBoundedTimer (так как я все еще думаю, что у вас должен быть таймер, чтобы не переопределять привязку на неопределенный срок в случае, если внешнее значение не обновляется).

Если у вас нет контроля над виджетом, я бы остановился на подходящем интервале для tempBoundedTimer

(В любом случае, я не добавляю таймер в каждом экземпляре виджета, это очень приятно)

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    property real externalValue: (Math.random()* 50).toFixed(0)

    Timer {
        running: true
        repeat: true
        interval: 1000
        onTriggered: {
            // Simulate externalValue changes out of our control
            externalValue = (Math.random()* 50).toFixed(0)
        }
    }


    Component.onCompleted: {
        // Unknown external binding set by developer using textItem widget
        textItem.text = Qt.binding(function(){return externalValue})
    }

    Column {

        Text {
            id: textItem
            text: ""

            property real internalValue: (Math.random()* 50).toFixed(0)

            Timer {
                id: tempBoundedTimer
                repeat: false
                interval: 2000
            }

            states: [
                State {
                    when: tempBoundedTimer.running
                    PropertyChanges {
                        target: textItem
                        text: "internal:" + internalValue
                    }
                }
            ]
        }

        Button {
            text: "Change Internal Value"
            onClicked: {
                textItem.internalValue = (Math.random()* 50).toFixed(0)
                tempBoundedTimer.start()
            }
        }
    }
}

Кстати, я думаю, что ваш объект Binding действительно должен работать, если when связан с tempBoundedTimer.running, но я не смог заставить его играть хорошо. Кажется, Qt.binding имеет приоритет

...