¿Cuáles son algunos métodos de diseño estándar para agregar GUI a una aplicación de línea de comandos? [cerrado]

8

Tengo una aplicación Linux C integrada que se ejecuta con una CLI simple. Ahora tengo la tarea de crear una GUI que logre la misma funcionalidad que el programa de línea de comandos. No soy un diseñador de GUI consumado y la mayoría si mi experiencia es en codificación C profundamente incrustada.

Mi pensamiento inicial es usar qtcreator para crear la GUI, pero hay varios problemas sobre los que estoy reflexionando.

  • En el futuro quiero mantener tanto el programa CL como el programa GUI, y preferiblemente incluso hacer que sean exactamente el mismo ejecutable que se puede iniciar en cualquier modo. ¿A menos que sea una mala idea?
  • Mi código está en C hasta ahora, y qt es nativamente c ++
  • Me gustaría una correlación directa en la que las pulsaciones de botones en la GUI llamen a las mismas funciones que llamo desde la CLI
  • ¿Cómo hago esto mejor de manera limpia y eficiente? ¿Hay alguna otra tecnología o biblioteca que simplifique esto? No tengo que usar qt si hay algo mejor.
Brandon Yates
fuente
Más o menos depende de los requisitos de latencia, si los hay. Para las GUI simples, puede usar lenguajes de secuencias de comandos (Yad / Zenity / GTKdialog / TclTk / ... etcétera, etcétera) para crear rápidamente un prototipo de la apariencia. Por lo general, debe evitar la correspondencia 1-a-1 entre la GUI y el código; la idea es hacer que la interfaz sea utilizable e intuitiva, no forzar al usuario a aprender los aspectos internos de su aplicación.
Deer Hunter
Este artículo objectmentor.com/resources/articles/TheHumbleDialogBox.pdf probablemente lo ayudará: explica "presentador de vista de modelo", que es el mejor enfoque que conozco para hacer que la interfaz de usuario sea intercambiable.
Doc Brown

Respuestas:

11

Podría darle algunas pautas aproximadas sobre cómo crear la GUI equivalente para una aplicación CLI, en cuanto al diseño. La forma en que realmente haría las llamadas está fuera del alcance de esta respuesta.

  • interruptores como -p -v, etc.son casillas de verificación

ingrese la descripción de la imagen aquí

  • opciones mutuamente excluyentes son un grupo de botones de radio

ingrese la descripción de la imagen aquí

  • los parámetros que son un nombre de archivo son un cuadro de texto con un botón "elegir" que muestra un cuadro de diálogo de elegir archivo cuando se presiona

ingrese la descripción de la imagen aquí

  • los parámetros de cadena en general son cuadros de texto
  • los parámetros numéricos pueden ser cuadros de texto, cuadros combinados o cuadros giratorios, dependiendo de los valores conocidos, restringidos en un rango o de forma libre.

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

  • los usos totalmente divergentes se separan en páginas con pestañas (por ejemplo, agregar el metaconmutador "commit" a git, cambia todo el conjunto de parámetros y parámetros esperados / permitidos)

ingrese la descripción de la imagen aquí

  • Una vez que se ingresan los parámetros, un botón ejecuta la acción

ingrese la descripción de la imagen aquí

Nota: la validación de entrada debe ser proactiva , es decir, debe evitar que el usuario ejecute la acción cuando no se hayan ingresado parámetros obligatorios, desactivando el botón de ejecución y, en general, desactivando o activando elementos GUI para transmitir el uso adecuado. En las aplicaciones CLI, el usuario simplemente ejecuta el comando y recibe un mensaje de error, es decir, la validación es reactiva.

Tulains Córdova
fuente
1
Muy buen consejo. No es una respuesta en sí misma, sino un excelente "cómo" suplementar a las otras respuestas "qué hacer".
Bobson
6

Por lo general, esto se puede resolver escribiendo una interfaz gráfica de usuario que construya una línea de comando . En ese punto, simplemente llame a la antigua función CLI "main ()" con los argumentos en el orden apropiado.

Lo que debe hacer entonces depende de la salida. Podría hacerlo bien envolviendo todo printf()en una función variada de salida genérica, que en la versión CLI simplemente pasará el control printfmientras que en la versión GUI envía la salida a una ventana de registro desplegable o algo así.

De esta forma, la aplicación de la CLI permanece prácticamente sin cambios y el front-end de la GUI, aunque pierde eficiencia, permanece débilmente acoplado y se puede mantener de forma independiente (en algunos casos, una maqueta, o incluso una alternativa real a la GUI) podría ser independiente aplicación que luego genera el binario CLI con los argumentos adecuados; más o menos lo que puede hacer con AutoIt en Windows, por así decirlo).

Pero esto depende en gran medida de lo que realmente hace la aplicación . Este enfoque aún puede llevarse a cabo en mayor o menor medida, pero puede resultar incómodo si, por ejemplo, desea ejecutar la rutina CLI cíclicamente o algo así; o si el programa esperaba operar con una entrada de stdin.

LSerni
fuente
Idea interesante, aunque realmente no veo la ventaja de construir un argumento de línea de comando en lugar de simplemente llamar al mismo método desde ambos lugares. Además, parece extraño estar potencialmente invocando main varias veces a lo largo de la vida del programa GUI.
jhewlett
1
Si no haces esto, corres el riesgo de que la interfaz gráfica de usuario pueda hacer cosas que no son posibles desde una línea de comandos.
Pieter B
1
@jhewlett, este es ciertamente un atajo. main()en sí mismo debería ser poco más que un front-end analizador de argumentos para el cuerpo del programa "real". Pero si ese hubiera sido el caso, creo que adoptar su opción (que es la mejor) habría sido tan sencillo como para no justificar una pregunta en primer lugar.
LSerni
3

lo primero que debe hacer es hacer que el back-end (detrás de la CLI actual) esté separado de la interfaz (la CLI)

esencialmente separe la vista / controlador (CLI) del modelo para que todo el código de funcionalidad se pueda separar en su propio módulo independiente (que puede compilar en una biblioteca estática, por ejemplo)

entonces puede usar la interfaz C pública de ese módulo para codificar en su GUI QT

para la correlación de las pulsaciones de los botones, hay una amplia implementación de ranura de señal en QT y el creador de QT manejará una gran cantidad de enlaces por usted (es tan simple como hacer clic derecho-> ir a la ranura ...-> hacer clic () - > tipo foo())

monstruo de trinquete
fuente
1

Si su aplicación CLI actual utiliza un formato de entrada y salida razonablemente estructurado (particularmente el resultado. Debe estar estructurado lo suficiente como para ser analizado por una máquina), entonces siempre puede crear una aplicación GUI separada que se comunique con la aplicación CLI a través de tuberías y / o archivos temporales.

Para integrar la GUI con la aplicación actual, debe ser capaz de separar completamente el manejo de E / S del resto de la aplicación, para poder construir la parte sin E / S como una biblioteca y atornillar una interfaz de usuario (ya sea GUI o CLI) a eso. Si la aplicación original nunca fue diseñada para esto, podría ser una tarea difícil, ya que es muy fácil dispersar las printfllamadas por todo el lugar.

El hecho de que Qt sea C ++ y su aplicación esté en C no debería ser un obstáculo importante para una aplicación integrada, siempre que la interfaz de la parte de back-end esté escrita en el subconjunto común de C y C ++. Entonces solo tienes que superar la curva de aprendizaje de C ++.

Bart van Ingen Schenau
fuente