Dialog creation/es

En esta página vamos a mostrar cómo crear un simple letrero de diálogo con Qt Designer, la herramienta oficial de Qt para el diseño de interfaces, después lo convertiremos en código de Python, para luego utilizarlo en FreeCAD. Vamos a suponer en el ejemplo que ya sabes cómo editar y ejecutar archivos de guión de Python, y que puedes hacer cosas simples en una ventana de terminal, como navegar, etc. También debes tener, por supuesto, PyQt instalado.

Diseñar el letrero de diálogo
En las aplicaciones de CAD, el diseño de una buena interfaz de usuario (UI, User Interface) es muy importante. Casi todo lo que el usuario haga será a través de alguna parte de la interfaz: leyendo los letreros de diálogo, pulsando los botones, eligiendo entre iconos, etc. Así que es muy importante pensar cuidadosamente lo que quieres hacer, cómo deseas que el usuario se comporte, y cómo será el flujo de trabajo de tu acción.

Hay un par de conceptos que debes saber a la hora de diseñar la interfaz:


 * Letreros de diálogo Modales/no modales: Un letrero de diálogo modal aparece delante de la pantalla, deteniendo la acción de la ventana principal, obligando al usuario a responder al cuadro de diálogo, mientras que un cuadro de diálogo no modal permite seguir trabajando en la ventana principal. En algunos casos la primera opción es mejor, pero en otros casos no.
 * Identificación de lo que es necesario y lo que es opcional: Asegúrate de que el usuario sabe lo que debe hacer. Etiqueta todo con la descripción adecuada, utiliza etiquetas de información sobre el uso de las herramientas, etc.
 * Separar los comandos de los parámetros: Esto se hace generalmente con botones y cuadros de texto. El usuario sabe que al hacer clic en un botón, se produce una acción mientras que al cambiar un valor dentro de un cuadro de texto va a cambiar un parámetro en alguna parte. Hoy en día, sin embargo, los usuarios suelen conocer bien lo que es un botón, lo que es un cuadro de texto, etc. El conjunto de herramientas de interfaz que está utilizando, Qt, es el conjunto de herramientas más avanzado, y no tendrás que preocuparte mucho de hacer las cosas claras, puesto que ya va a ser muy clara por sí misma.

Así que, ahora que tenemos bien definido lo que haremos, es el momento para abrir el diseñador de Qt Designer. Diseñemos un letrero de diálogo muy sencillo, como este:



Después podremos utilizar este letrero de diálogo en FreeCAD para producir un bonito plano rectangular. Puede que no veas muy útil hacer planos rectangulares, pero será fácil cambiarlo más adelante para hacer cosas más complejas. Cuando lo abras, el aspecto de Qt Designer es el siguiente:



Es muy sencillo de utilizar. En la barra de la izquierda tienes elementos que pueden ser arrastrados a tu widget. En el lado derecho tienes los paneles de propiedades mostrando todo tipo de propiedades editables de los elementos seleccionados. Comencemos ahora con la creación de un nuevo widget o complemento. Selecciona "letrero de diálogo sin botones", ya que no queremos el formato predeterminado de botones Ok/Cancelar. A continuación, arrastra sobre tu widget 3 etiquetas, una para el título, una para escribir "Altura" y otra para escribir "Ancho". Las etiquetas son textos sencillos que aparecen en tu widget, simplemente para informar al usuario. Si seleccionas una etiqueta, en la parte derecha aparecerán varias propiedades que puedes cambiar si lo deseas, como el estilo de fuente, altura, etc.

A continuación, agrega 2 LineEdits, que son cuadros de texto que el usuario puede rellenar, uno para la altura y uno para el ancho. También en este caso, podemos editar las propiedades. Por ejemplo, ¿por qué no establecer un valor predeterminado? digamos 1.00 para cada uno. De esta manera, cuando el usuario vea el letrero de diálogo, ambos campos ya estarán rellenados, y si está conforme puede pulsar el botón directamente, ahorrando un tiempo precioso. A continuación, agrega un PushButton, que es el botón que el usuario deberá pulsar después de llenar los 2 campos.

Ten en cuenta que he elegido aquí controles muy sencillos, pero Qt tiene muchas más opciones, por ejemplo, podría utilizar Spinboxes en lugar de LineEdits, etc. Echa un vistazo a lo que está disponible, seguramente tendrás otras ideas.

Eso es prácticamente todo lo que necesitamos hacer en Qt Designer. Una última cosa, sin embargo, vamos a cambiar el nombre de todos nuestros elementos con nombres más adecuados, de modo que sea más fácil identificarlos en nuestros archivos de guión:



Convertir nuestro diálogo a Python
Ahora, vamos a salvar nuestro widget en alguna parte. Se guardará como un archivo .ui, que fácilmente se convertirá en un archivo de guión de Python por medio de pyuic. En Windows, el programa pyuic se ve enriquecido con PyQt (por verificar), en linux es probable que tengas que instalarlo por separado desde tu gestor de paquetes (en sistemas basados en Debian, es parte del paquete de herramientas PyQt4-dev-tools). Para realizar la conversión, tendrás que abrir una ventana de terminal (o una ventana de símbolo de sistema en Windows), ve a donde guardaste el archivo .ui, y escribe: En algunos sistemas el programa se llama pyuic4 en lugar de pyuic. Esta operación simplemente convertirá el archivo .ui en un archivo de guión de Python. Si abrimos el archivo mywidget.py, su contenido es muy fácil de entender: Como verás, tiene una estructura muy simple: se crea una clase denominada Ui_Dialog, que almacena los elementos de interfaz de nuestro widget o complemento. Esa clase tiene dos métodos, uno para la configuración del widget, y otro para la traducción de su contenido, eso es parte del mecanismo general de Qt para la traducción de elementos de la interfaz. El método de configuración simplemente crea, uno a uno, los widgets tal como los has definido en Qt Designer, y establece sus opciones, como hayamos decidido con anterioridad. Despues, toda la interfaz se traduce, y por último, se conectan las ranuras (slots) (hablaremos de eso más adelante).

We can now create a new widget, and use this class to create its interface. We can already see our widget in action, by putting our mywidget.py file in a place where FreeCAD will find it (in the FreeCAD bin directory, or in any of the Mod subdirectories), and, in the FreeCAD python interpreter, issue: And our dialog will appear! Note that our python interpreter is still working, we have a non-modal dialog. So, to close it, we can (apart from clicking its close icon, of course) issue:

Making our dialog do something
Now that we can show and hide our dialog, we just need to add one last part: To make it do something! If you play a bit with Qt designer, you'll quickly discover a whole section called "signals and slots". Basically, it works like this: elements on your widgets (in Qt terminology, those elements are themselves widgets) can send signals. Those signals differ according to the widget type. For example, a button can send a signal when it is pressed and when it is released. Those signals can be connected to slots, which can be special functionality of other widgets (for example a dialog has a "close" slot to which you can connect the signal from a close button), or can be custom functions. The PyQt Reference Documentation lists all the qt widgets, what they can do, what signals they can send, etc...

What we will do here, is to create a new function that will create a plane based on height and width, and to connect that function to the pressed signal emitted by our "Create!" button. So, let's begin with importing our FreeCAD modules, by putting the following line at the top of the script, where we already import QtCore and QtGui: Then, let's add a new function to our Ui_Dialog class: Then, we need to inform Qt to connect the button to the function, by placing the following line just before QtCore.QMetaObject.connectSlotsByName(Dialog): This, as you see, connects the pressed signal of our create object (the "Create!" button), to a slot named createPlane, which we just defined. That's it! Now, as a final touch, we can add a little function to create the dialog, it will be easier to call. Outside the Ui_Dialog class, let's add this code: (Python reminder: the __init__ method of a class is automatically executed whenever a new object is created!) Then, from FreeCAD, we only need to do: That's all Folks... Now you can try all kinds of things, like for example inserting your widget in the FreeCAD interface (see the Code snippets page), or making much more advanced custom tools, by using other elements on your widget.

The complete script
This is the complete script, for reference:

Method 1
An example of a dialog box complete with its connections. Here the same window but with an icon on each button. Here the code to display the icon on the pushButton, change the name for another button, (radioButton, checkBox) and the path to the icon. The command UserAppData gives the user path AppHomePath gives the installation path of FreeCAD This command reverses the horizontal button, right to left.

Method 2
Another method to display a window, here by creating a file QtForm.py which contains the header program (module called with import QtForm), and a second module that contains the code window all these accessories, and your code (the calling module).

This method requires two separate files, but allows to shorten your program using the file ' ' QtForm.py ' ' import. Then distribute the two files together, they are inseparable.

The file QtForm.py The appellant, file that contains the window and your code.

The file my_file.py

The connections are to do, a good exercise.

Some useful commands
By using the characters with accents, where you get the error :

Several solutions are possible.

UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-2: invalid data or with the procedure

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 9: ordinal not in range(128)

or with the procedure or or or