Los enlaces de propiedad Qt/QML se rompen después de una asignación de JavaScript

 C Programming >> Programación C >  >> Tags >> Qt
Los enlaces de propiedad Qt/QML se rompen después de una asignación de JavaScript

Los enlaces de propiedad son uno de los conceptos más poderosos en Qt/QML. Los enlaces de propiedad le permiten especificar relaciones entre diferentes propiedades de objetos. Cuando las dependencias de una propiedad cambian de valor, la propiedad se actualiza automáticamente de acuerdo con la relación especificada. El motor QML supervisa las dependencias de propiedades (es decir, las variables en la expresión de enlace). Cuando se detecta un cambio, el motor QML vuelve a evaluar la expresión de enlace y aplica el nuevo resultado a la propiedad. Una advertencia poco conocida con los enlaces de propiedad es que se interrumpen después de una asignación estática de JavaScript (property = value ). Esta publicación le muestra los diferentes comportamientos y cómo usar Qt.binding() para asignar enlaces de propiedad a través de JavaScript.

Tenga en cuenta que este comportamiento está previsto, documentado y puede ser útil en situaciones en las que desea romper deliberadamente un enlace de propiedad.

Esta publicación tiene como objetivo informarle sobre los diferentes comportamientos, ya que puede resultar confuso si no está al tanto de lo que está sucediendo. Un colega mío estaba trabajando en un error, no estaba al tanto de este comportamiento y le costó dos horas darse cuenta de que era el problema subyacente. También podría pasarme a mí cuando estás metido hasta las rodillas en una sesión de depuración.

Demostración

La imagen de arriba demuestra el problema.

Los mejores Button (id: boundButton ) text la propiedad está vinculada a TextField (id: bindableTextField ) text propiedad, por lo que cuando edita el texto, el texto del botón se actualiza automáticamente.

El segundo botón rompe el enlace haciendo una asignación de JavaScript en su onClicked función:

onClicked: boundButton.text = "Binding broken"

Si ha hecho clic en el botón y luego cambia el texto en el TextField ,el texto del botón ya no refleja el texto que ha escrito.

El último botón restaura el enlace de propiedad usando el Qt.binding() función:

onClicked: boundButton.text = Qt.binding(function () {
            return bindableTextField.text
        })
    }

Una sintaxis un poco complicada, pero hace el trabajo.

Qt.binding()

La documentación establece lo siguiente:

De manera confusa, esa página tiene ejemplos para el segundo caso de uso, no para el primero. Los ejemplos más simples están en la otra página del documento, transcritos a continuación:

El Rectángulo a continuación inicialmente asegura que su altura sea siempre el doble de su width . Sin embargo, cuando se presiona la tecla de espacio, el valor actual de width*3 será asignado a la altura como un valor estático . Después de eso, la altura permanecerá fija en este valor, incluso si cambia el ancho. La asignación del valor estático elimina el enlace.

Rectangle {
    width: 100
    height: width * 2

    focus: true
    Keys.onSpacePressed: {
        height = width * 3
    }
}

Si la intención es darle al rectángulo una altura fija y detener las actualizaciones automáticas, entonces esto no es un problema. Sin embargo, si la intención es establecer una nueva relación entre el ancho y el alto, entonces la nueva expresión vinculante debe incluirse en el Qt.binding() función en su lugar:

Rectangle {
    width: 100
    height: width * 2

    focus: true
    Keys.onSpacePressed: {
        height = Qt.binding(function() { return width * 3 })
    }
}

Ahora, después de presionar la tecla de espacio, la altura del rectángulo continuará actualizándose automáticamente para que siempre sea tres veces su ancho.

El otro caso de uso, según mi experiencia, no se usa con frecuencia, o al menos no en los proyectos en los que he trabajado. La creación dinámica de objetos QML es divertida al principio, pero se pierde la seguridad de tipo y todo son cadenas, por lo que cambiar un nombre funcionará bien al principio, hasta que obtenga errores de tiempo de ejecución en otro lugar. Tal vez estoy arruinado por la seguridad en tiempo de compilación, pero un pequeño error tipográfico o un cambio de nombre me ha pillado más de lo que me gustaría admitir. Mientras que en C++ ya no se compilará más.