Depuración de Rectangle{} en QML, igual que printf(), pero para QT

 C Programming >> Programación C >  >> Tags >> Qt
Depuración de Rectangle{} en QML, igual que printf(), pero para QT

Recientemente he estado usando una técnica de depuración en QT/QML que he decidido llamar Rectangle{} depuración, en la misma línea que printf() depuración QML es un lenguaje de marcado (parte del marco QT) como HTML/CSS, JavaScript en línea que puede interactuar con el código C++ de su aplicación (QT). QML tiene el concepto de anchors para el posicionamiento relativo de los elementos. En total, anchors funciona bastante bien, pero puede volverse complejo cuando entran en juego la herencia y los diseños complicados. El Rectangle{} estilo de depuración coloca un rectángulo semitransparente con un borde alrededor de su elemento para que pueda visualizar el posicionamiento y ver qué efecto tienen sus cambios. Este artículo muestra un ejemplo en el que recientemente apliqué este estilo de depuración en el trabajo en la interfaz de usuario de nuestra máquina de café, incluidos algunos consejos para hacer printf() reales. depuración de estilo (pero con Console.log ).

He escrito sobre QT / QML antes, ese artículo se centró en la señalización y las ranuras, un método para comunicarse entre C ++ y QML.

El sistema de anclaje Qt Quick le permite definir relaciones entre las líneas de anclaje de diferentes elementos. Por ejemplo, puedes escribir:

Rectangle { id: rect1; ... }
Rectangle { id: rect2; anchors.left: rect1.right; ... }

En este caso, el borde izquierdo de rect2 está vinculado al borde derecho de rect1 , produciendo lo siguiente:

Como se dijo, esto se vuelve complejo rápidamente, especialmente cuando los anclajes/posiciones dependen de variables dinámicas que llegan a través de señales desde el lado de C++. QT Design Studio tampoco se puede utilizar en nuestros proyectos debido a limitaciones específicas de la plataforma.

¿Qué es printf()? depuración? Es una técnica que lleva el nombre de la función ubiquitousC. Se utiliza para describir el trabajo de depuración realizado mediante la inserción de comandos que emiten información de estado elegida con más o menos cuidado en puntos clave del flujo del programa, observando esa información y deduciendo qué es lo que está mal en función de esa información.

Prefiero un depurador dedicado, pero tiene que ser bueno e integrado en mi IDE. CLion tiene esto, Visual Studio tiene uno razonable y el depurador QML de QT Creator es simplemente malo.

Para elementos visuales como en QML, es más difícil depurar el posicionamiento y cosas relativas. Además de eso, QT Creator tiene un depurador QML, pero es horrible de usar. No responde, faltan puntos de interrupción, todo tipo de otras cosas raras que simplemente funcionan terriblemente. El uso de este truco del rectángulo hace que los elementos, los límites y los cambios sean muy visibles. Para centrar un objeto, usas anchors.centerIn: parent o anchors.horizontalCenter: parent.horizontalCenter ? Con un gran rectángulo alrededor de su cambio, es mucho más visible lo que hace un cambio.

Rectángulo{} depuración

Recientemente tuve que implementar la función de café sin contacto para una de las interfaces de usuario de nuestra máquina, que usa QT. El control QML ya existía, pero tenía que colocarse en algunas pantallas, reemplazando condicionalmente a otro elemento dependiendo de una configuración. El primer intento de colocar el control en ese otro elemento resultó en un elemento pequeño y descentrado. A continuación se muestra una imagen que muestra el primer intento a la izquierda y el resultado final a la derecha:

La borrosidad en las capturas de pantalla se debe al hecho de que las redimensioné para que encajaran mejor en el sitio, en la máquina son súper nítidas.

El elemento que se reemplazó condicionalmente, se redimensionó y se centró, se copió la sintaxis QML y resultó en algo inesperado. Lo primero que hice fue poner un rectángulo alrededor del contenedor, para visualizar lo que estaba pasando:

Rectangle {
    anchors.fill: parent
    color: "#ffffff"
    visible: true
    opacity: 0.8
    border.color: "#ff0000"

    //insert your objects here
}

Se ve así:

Como puede ver, la nueva imagen qr no está exactamente en la esquina superior izquierda, por lo que dentro del control QR se está posicionando. Pongamos otro Rectangle en el control de código QR para ver lo que está haciendo. Esta vez el color de fondo es naranja claro, para distinguirlo del contenedor exterior:

Dentro del control QR el tamaño tampoco es el esperado, el centrado es correcto. Recuerde, ese control específico ya se usa en otras IU y funciona correctamente. Juguemos con el Image.Fillmode , Pad o PreserveAspectFit debería hacer el truco, así como algunos anchors.fill: parent rociado aquí y allá:

Casi allí, como puedes ver, el Code: el texto ahora está fuera de ambos controles. Que tiene un anchor.top: qrimage.bottom , lo cual es correcto, pero si se recortara este control, el texto no sería visible. Si no hubiera usado este Rectangle{} método de depuración, no lo habría notado, lo que podría causar errores en el futuro.

Probemos con Image.width: ### * 0.85 :

Mejor, pero cuando el control es más grande, todavía no es correcto, demasiado espacio en la parte inferior. Arreglar eso está fuera del alcance de este artículo. Continúe centrando el control. Ese fue un caso de la combinación correcta de anchors.fill: parent y anchors.horizontalCenter: parent.horizontalCenter en unos pocos controles. Te ahorraré los detalles, después de unos minutos encontré el combo correcto:

Lo único que queda ahora es eliminar los rectángulos (o, aún peor, hacerlos transparentes) y terminar la característica.

Sin la técnica de depuración del rectángulo, probablemente no habría visto que el texto está fuera de la imagen. O habría discusión sobre si un control está en el centro exacto. Hacerlo visual y visible es mucho más útil que quedarse mirando un depurador en este caso.

Si se pregunta, así es como se ve la página web después de haber escaneado el código QR:

Este código QR específico nunca funcionó, ya que solo estaba activo en un entorno de desarrollo, pero es posible que se pregunte qué sucedería si escaneara el código. Te da una página web con todos los consumos de las máquinas, elige uno, personaliza la bebida y pulsa Ordenar. La máquina comienza a producirlo, todo sin que el usuario tenga que tocar la pantalla. Utiliza MQTT en el backend, menos de 7 MBa al mes en uso de datos, muy receptivo, realmente genial para desarrollar. Pero esa es una historia para otro día.

Depuración QML de Console.log

QML combina el lenguaje de marcado con JavaScript en línea, lo que en mi caso puede ser útil durante la depuración. Por ejemplo, la visibilidad de un elemento se puede determinar mediante las propiedades de QML o mediante señales y ranuras de C++. Reemplazando el visible: varName con una llamada de función de JavaScript, podemos registrar el valor en la consola. Al hacer eso, puedo excluir ese valor booleano si un elemento es invisible, pero debería ser visible. Ayuda a determinar si el estilo (índice z, por ejemplo) es el problema o el valor real devuelto.

Aquí hay un archivo QML de ejemplo:

Item {
  function logAndReturnValue(varToLog)
  {
    console.log("value: " + varToLog);
    return varToLog;
  }
  property bool varName: false;

  Text {
    visible: logAndReturnValue(varName)
    text: "Example Text"
  }
}

Esta sencilla función de ejemplo toma una variable, la registra en la consola y devuelve el resultado. El Text elemento tiene la línea visible: , que es el boolean valor verdadero o falso, u otra variable que contenga un valor booleano o una función que devuelva un valor booleano. Al usar señales, puede configurar esto a través del código C++, vea mi otro artículo de ejemplo para saber cómo funciona.

Efectivamente, podría escribir visible: varName , pero con este método de registro, también se imprime.

Además de usar este método, también puede conectarse al Component.onCompleted manejador de señales, que se emite después de que se haya instanciado un objeto:

Text {
    Component.onCompleted: console.log("Text onCompleted.")
    text: "Example Text"
}

En mi experiencia, el depurador QML es una molestia para trabajar, ni remotamente tan pulido como la integración GDB de CLion. También es un poco extraño a veces, no actualizar con resultados, no pasar por alto correctamente, todo tipo de pequeños problemas. A menudo prefiero esta depuración estilo printf en QML debido a lo malos que son QT Creator y su depurador QML.