GUI universal ~ = fin de la miseria

Para mí, la GUI ideal es una aplicación que no requiere programación, diseño, mantenimiento, y es capaz de funcionar por igual con cualquier lenguaje y en cualquier plataforma sin ningún ajuste. ¿Es posible en nuestra vida que intentemos resolverlo?

Es fácil aprender individualmente algo de Vue / React, JavaFX, Python PyQt, ... pero obtener datos e interactuar con el zoológico de software de una manera simple y elegante sin pensar en el sistema operativo del usuario / navegadores / plataformas es una tarea no resuelta para tales herramientas. No quiero entrar en el nuevo marco (incluso el antiguo, olvidado), cambiar el lenguaje de programación, rastrillar el rastrillo y obstruir mi cabeza con basura. Quiero programar exactamente mi tarea, sin distraerme con la lucha con todo tipo de marcos GUI. Y encontré una solución para mí.

Como protocolo de intercambio, utilizaremos Json como el mejor formato en términos de popularidad / comprensión / legibilidad / soporte para todos los lenguajes de programación en un grado u otro.

El servidor envía datos Json, según los cuales nuestra GUI de la aplicación debe diseñar una imagen que satisfaga las especificaciones de una hermosa GUI. Google con su diseño de materiales es hoy el estándar, así que tómalo.

Los requisitos para una GUI moderna incluyen la presencia de elementos estándar, como botones, campos de entrada, tablas, etc. Permítanos estimar cómo usar el conjunto mínimo de convenciones para decirle a la GUI que necesitamos ciertos elementos en la pantalla. Aquí están los principales:

  • Botón sin estado {'nombre': 'Empújame'}. Si el elemento contiene solo un nombre, entonces es un botón.
  • El campo de entrada es {'nombre': 'Edítame', 'valor': ''} porque el valor de tipo es una cadena.
  • El botón de cambio {'nombre': 'Mi estado', 'valor': falso} porque el tipo falso es booleano.
  • Seleccione de la lista {'nombre': 'Cambiar algo', valor: 'opción1', opciones = ['opción1', 'opción2', 'opción3']}
  • {‘name’:’Image, ‘url'’: ’..’, ‘width’: .., ‘height’:… }
  • {‘name’:’My table’, 'headers'=[‘Name’, ‘Synonym’], rows = [
    [‘young’, ‘youthful’],
    [‘small’, ‘ meager’],
    ...]
    }

Para personalizar, puede configurar el tipo de elemento en {type: 'ButtonSwitcher'} si el tipo seleccionado automáticamente por JSON no le conviene. Esto es posible cuando el mismo JSON se puede mostrar en más de una forma. Por ejemplo, 'Seleccionar de una lista' puede representarse como un campo de entrada con una lista desplegable, o también puede ser un conjunto horizontal de botones, uno de los cuales está activo y corresponde al valor actual.

Con un pequeño número de opciones, tiene sentido usar automáticamente la opción del botón, con un gran número (más de 3): un campo de selección de entrada. Nuestra propia GUI elige la mejor manera de renderizar, pero si realmente la necesita, escriba: ... para ayudar. Normalmente, el tipo no es necesario y el diseñador de automóviles debe hacer frente por su cuenta.

Completemos la imagen en detalle:

  • si el nombre no se debe mostrar en la pantalla, debe comenzar con _;
  • - , ‘icon’: ‘ Material Design ’; push - {‘name’: ‘_Check’, ‘icon’: ‘check’}
  • , Viewers, , ‘colors’, ‘params’,… // . — , .

Para la agrupación lógica de elementos, presentamos el concepto de un bloque que agrupa elementos relacionados lógicamente en un bloque visual.

{'name': 'Block 1', 'elems': [{'name': '_Check', 'icon': 'check'}, ...]}
Dentro del bloque, todos los elementos deben tener nombres únicos, ya que son id .

Normalmente, los bloques se construyen horizontalmente si no pueden caber todo en la pantalla (comenzaron la GUI de la aplicación en un dispositivo móvil, por ejemplo), el diseñador automático los oculta, pero agrega iconos a la barra de herramientas que permiten abrirlos con un toque. Esto le brinda la opción de trabajar con una GUI compleja incluso en pantallas pequeñas.

El nivel superior de descripción es Pantalla. Parece que {'nombre': 'Screan', bloques: [..], menú: [{'nombre': 'Pantalla', 'icono': ..,}, ..], 'barra de herramientas': [conjunto JSON - elementos (botones, campos, lo que sea)]}

Agregue detalles de implementación para la uniGUI condicional que admite nuestro protocolo JSON. Es un proceso separado que se comunica con el servidor de datos Websocket y proporciona la visualización de sus datos con informes posteriores de todas las actualizaciones de estos datos que son importantes para el servidor.

Al conectarse al servidor, uniGUI espera recibir Screen. Una vez recibido, diseña y dibuja la información resultante de una manera óptima para la pantalla actual para el usuario, luego espera una reacción del usuario y del servidor. Desde la imagen de datos construida, el servidor recibe una secuencia de mensajes JSON que describen completamente lo que hizo el usuario. Se ven como ['Bloque', 'Elem', 'tipo de acción', 'valor'], donde 'Bloque' y 'Elem' son los nombres del bloque y elemento, el valor es el valor del evento.

El servidor puede aceptar el cambio o revertirlo enviando una ventana de información sobre la discrepancia. Puede abrir un cuadro de diálogo, que se describe como un bloque, y tiene más. el parámetro 'botones', que describe los botones en el diálogo. El cliente muestra instantáneamente los datos del servidor actual y sus cambios. Solo se envían los objetos modificados por el servidor. Para recibir eventos y asegurar su procesamiento, crearemos una capa Websocket (marco), que traducirá automáticamente los mensajes en llamadas a controladores que están asociados con nuestros datos (objetos).

Toda la magia en el servidor se reduce al hecho de que nuestros datos mostrados deben estar vinculados a la capa de tal manera que se garantice su traducción automática a JSON y que se devuelvan las notificaciones de la actividad del usuario sin ningún tipo de codificación. Dado que depende de las capacidades de un idioma en particular, entonces, para cada idioma, la capa puede tener diferentes opciones, tanto arquitectónica como específicamente.

Por ejemplo, en un caso, la capa tiene una carpeta de capturas de pantalla, cada uno de los módulos en el que tiene una descripción de una pantalla en Python. Al inicio, la capa lee las pantallas, le da al usuario una con prioridad global = 0. Todos los datos se transmiten automáticamente usando jsonpickle. Los elementos complejos tienen su propia "inteligencia", eliminando el cuidado de los detalles del programador. Por ejemplo, una tabla recibe un conjunto de filas, en las que, por defecto, la fila id puede estar ausente cuando el número de datos en la fila == el número de elementos en los encabezados. En este caso, cuando el usuario selecciona una fila o edita su contenido, el servidor enviará el ID al índice en fila como ID ee. Si el número de datos en la fila es uno más que en los encabezados, el último elemento en las filas se interpreta como id y es lo que se envía al servidor. Dicha automatización simplifica enormemente la vida donde no necesita detalles,pero si de repente lo necesita, está disponible de la manera menos laboriosa.

La tarea de proporcionar traducción automática en JSON, siguiendo un formato que ocupa una o dos páginas, es completamente solucionable en cualquier idioma (eso espero).

Para no discutir la aplicabilidad de este enfoque para aplicaciones complejas, a continuación se presentan capturas de pantalla como las descritas por uniGUI escritas en aleteo. La elección recayó en él para multiplataforma y la falta de capas adicionales como JS / Chrome. En el flutter minus, puede escribir un soporte de escritorio repugnante y una baja calidad del código de la capa superior (elementos GUI), una arquitectura desagradable para actualizaciones puntuales y elementos de gestión como datos, que, sin embargo, se trata.



La GUI de la aplicación de flujo de mensajes -> servidor se ve así:

flutter: [Glosario, términos, =, 658]
flutter: [_Details, Links, @, @Folliculitis]
flutter: [_Details, Links, @, @Adolescent]
flutter: [toolbar, _Back, =, _Back]
flutter: [toolbar, _Forward, =, _Forward]
flutter: [toolbar, _Back, =, _Back]
flutter: [_Details, _Status, =, Virtual]
flutter: [_Details, _Status , =, Estable]
aleteo: [_Detalles, Enlaces, @,Inflamación]
flutter: [_Details, _Status, =, Virtual]
flutter: [_Details, _Status, =, Stable]
flutter: [toolbar, _Back, =, _Back]
flutter: [_Details, Links, @, @Folliculitis]

Habrá reduzca la velocidad de dicha GUI cuando espere eventos del servidor. No, porque la GUI funciona en el modo de notificación del servidor, reaccionando a todas las acciones del usuario como una GUI local normal. Por defecto, considera el silencio del servidor en las acciones del usuario como Ok. Al cambiar las pantallas, está claro que su descripción debe venir. Puede haber un retraso en comparación con la típica GUI integrada de la aplicación c.

Total. Hoy en día, con las herramientas actuales, es posible hacer una GUI que elimine el 90% del código de servicio triste estándar y no molestar dónde y cómo funcionará. Al menos para aplicaciones empresariales / científicas. Este artículo es una prueba de concepto de que crear un navegador de aplicaciones condicional no solo es posible, sino necesario.

All Articles