Módulo 13: Exportación y Uso del Archivo .ui
Cómo tu diseño se convierte en una aplicación real
Cómo tu diseño se convierte en una aplicación real
---
Objetivos de Aprendizaje
Al finalizar este módulo serás capaz de:
- Comprender la estructura de un archivo .ui
- Cargar archivos .ui directamente con QUiLoader
- Convertir archivos .ui a código Python con pyside6-uic
- Entender el flujo de trabajo diseñador → programador
- Organizar archivos .ui en un proyecto
- Usar la herramienta de línea de comandos de Custom Widgets
- Empaquetar recursos junto con archivos .ui
---
13.1 El Archivo .ui
Cuando guardas tu diseño en Qt Designer, se crea un archivo con extensión .ui. Este archivo es XML (texto estructurado) que describe cada widget, su posición, propiedades y conexiones.
🎨 ANALOGÍA DEL DISEÑO
>
El archivo .ui es como tu archivo .psd o .fig: contiene todo tu diseño editable. La diferencia es que en lugar de ser un formato propietario cerrado, es XML abierto que cualquier programa puede leer.
Estructura básica de un archivo .ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Mi Diálogo</string>
</property>
<property name="styleSheet">
<string notr="true">background-color: #1a1a2e;</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="titulo_label">
<property name="font">
<font>
<pointsize>20</pointsize>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">color: #ffffff;</string>
</property>
<property name="text">
<string>¡Hola Mundo!</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cerrar_btn">
<property name="text">
<string>Cerrar</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>cerrar_btn</sender>
<signal>clicked()</signal>
<receiver>Dialog</receiver>
<slot>close()</slot>
</connection>
</connections>
</ui>
Partes del archivo .ui
| Sección | Descripción |
|---|---|
| --------- | ------------- |
| ` |
Versión del formato .ui |
| ` |
Nombre de la clase que se generará |
| ` |
El widget principal y sus propiedades |
| ` |
Los layouts aplicados |
| ` |
Cada widget hijo con sus propiedades |
| ` |
Referencias a archivos de recursos (.qrc) |
| ` |
Las conexiones de Signals y Slots |
---
13.2 Método 1: Cargar directamente con QUiLoader
Este método carga el .ui directamente sin convertirlo. Es como abrir un PSD en Photoshop.
Código para cargar un .ui
from PySide6.QtWidgets import QApplication
from PySide6.QtUiTools import QUiLoader
from PySide6.QtCore import QFile
import sys
def main():
app = QApplication(sys.argv)
# Cargar el archivo .ui
loader = QUiLoader()
ui_file = QFile("mi_diseno.ui")
if not ui_file.open(QFile.ReadOnly):
print("Error: No se pudo abrir el archivo .ui")
sys.exit(1)
ventana = loader.load(ui_file)
ui_file.close()
if ventana is None:
print("Error: No se pudo cargar la interfaz")
sys.exit(1)
# Mostrar la ventana
ventana.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
Ventajas del Método 1
| Ventaja | Descripción |
|---|---|
| --------- | ------------- |
| **Sin conversión** | El .ui se carga directamente |
| **Cambios instantáneos** | Modifica el .ui y los cambios se reflejan al reiniciar |
| **Ideal para diseñadores** | No necesitas tocar Python para actualizar el diseño |
| **Archivo más pequeño** | No se genera código Python adicional |
Desventajas
| Desventaja | Descripción |
|---|---|
| ------------ | ------------- |
| **Acceso a widgets** | Necesitas usar `ventana.findChild()` para acceder a widgets específicos |
| **Rendimiento** | Ligeramente más lento que el método 2 (imperceptible en la práctica) |
| **Sin autocompletado** | El IDE no conoce los widgets del .ui |
Cómo acceder a widgets específicos
# Acceder a un widget por nombre
titulo = ventana.findChild(QLabel, "titulo_label")
titulo.setText("Nuevo texto")
# Acceder a un botón y conectar una señal
boton = ventana.findChild(QPushButton, "guardar_btn")
boton.clicked.connect(lambda: print("¡Guardado!"))
---
13.3 Método 2: Convertir a Python con pyside6-uic
Este método convierte el .ui a código Python. Es como "exportar" tu diseño a código.
Paso 1: Convertir el archivo
pyside6-uic mi_diseno.ui -o ui_mi_diseno.py
Paso 2: Usar el archivo generado
from PySide6.QtWidgets import QApplication, QDialog
from ui_mi_diseno import Ui_Dialog
import sys
class MiVentana(QDialog):
def __init__(self):
super().__init__()
# Crear la interfaz desde el archivo convertido
self.ui = Ui_Dialog()
self.ui.setupUi(self)
# Ahora puedes acceder a los widgets directamente
# self.ui.titulo_label.setText("Nuevo texto")
# self.ui.cerrar_btn.clicked.connect(self.close)
def main():
app = QApplication(sys.argv)
ventana = MiVentana()
ventana.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
Ventajas del Método 2
| Ventaja | Descripción |
|---|---|
| --------- | ------------- |
| **Acceso directo** | `self.ui.titulo_label` en lugar de `findChild()` |
| **Autocompletado** | El IDE conoce todos los widgets |
| **Rendimiento** | Ligeramente más rápido |
| **Integración con código** | Fácil de extender con lógica personalizada |
Desventajas
| Desventaja | Descripción |
|---|---|
| ------------ | ------------- |
| **Requiere conversión** | Debes convertir cada vez que cambias el .ui |
| **Archivo adicional** | Se genera un archivo .py extra |
| **No editar el .py** | Nunca edites el archivo generado manualmente |
---
13.4 Método 3: Usar Custom Widgets CLI
La biblioteca QT-PyQt-PySide-Custom-Widgets incluye herramientas de línea de comandos.
Convertir .ui a Python
Custom_Widgets --convert-ui mi_diseno.ui --qt-library PySide6
Monitorear cambios (hot reload)
Custom_Widgets --monitor-ui mi_diseno.ui --qt-library PySide6
Esto convierte automáticamente el .ui a Python cada vez que guardas cambios en Qt Designer.
Lanzar Qt Designer con plugins custom
Custom_Widgets --start-designer --plugins
---
13.5 Flujo de Trabajo Diseñador → Programador
En un equipo real, el flujo de trabajo ideal es:
┌─────────────────────────────────────────────────────────────┐
│ FLUJO DE TRABAJO │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ DISEÑADOR │ │ PROGRAMADOR │ │
│ │ │ │ │ │
│ │ Qt Designer│ │ Python + │ │
│ │ │ │ │ PySide6 │ │
│ │ ▼ │ │ ▲ │ │
│ │ Archivo .ui│ ──────► │ Carga .ui │ │
│ │ │ │ │ │ │
│ │ Modifica │ ──────► │ Se │ │
│ │ el .ui │ │ actualiza│ │
│ │ │ │ │ │ │
│ │ │ ◄────── │ Prueba │ │
│ │ │ │ y reporta│ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
Roles claros
| Rol | Responsabilidades | Herramientas |
|---|---|---|
| ----- | ------------------- | -------------- |
| **Diseñador** | Crear la interfaz visual, definir layouts, aplicar estilos, configurar signals/slots básicos | Qt Designer |
| **Programador** | Cargar el .ui, agregar lógica, conectar con bases de datos, manejar eventos complejos | Python + PySide6 |
🎨 ANALOGÍA DEL DISEÑO
>
Es como trabajar con un desarrollador web: tú diseñas en Figma, el programador convierte a HTML/CSS. La diferencia es que con Qt Designer, el archivo .ui YA es el "código" de la interfaz. No hay conversión manual necesaria.
---
13.6 Organización de Archivos en un Proyecto
Estructura recomendada
mi_proyecto/
├── main.py # Punto de entrada de la aplicación
├── requirements.txt # Dependencias (PySide6, etc.)
│
├── ui/ # Archivos .ui de Qt Designer
│ ├── main_window.ui
│ ├── dialog_config.ui
│ ├── dialog_registro.ui
│ └── components/
│ ├── sidebar.ui
│ └── tarjeta_producto.ui
│
├── src/ # Código Python generado (opcional)
│ ├── __init__.py
│ ├── ui_main_window.py
│ └── ui_dialog_config.py
│
├── resources/ # Recursos visuales
│ ├── recursos.qrc
│ ├── iconos/
│ │ ├── guardar.svg
│ │ └── eliminar.svg
│ └── imagenes/
│ └── logo.png
│
├── styles/ # Hojas de estilo
│ └── tema_oscuro.qss
│
└── json_styles/ # Temas JSON (Custom Widgets)
└── style.json
💡 CONSEJO: Mantén todos los archivos .ui en una carpeta
ui/separada del código Python. Esto hace que sea fácil para el diseñador encontrar sus archivos sin tocar el código.
---
13.7 Empaquetar la Aplicación
Cuando estés listo para distribuir tu aplicación:
Con PyInstaller
# Instalar PyInstaller
pip install pyinstaller
# Crear el ejecutable
pyinstaller --onefile --windowed --add-data "ui;ui" --add-data "resources;resources" main.py
Con cx_Freeze
# setup.py
from cx_Freeze import setup, Executable
setup(
name="Mi Aplicacion",
version="1.0",
description="Mi aplicacion de escritorio",
executables=[Executable("main.py", base="Win32GUI")],
include_files=[("ui/", "ui/"), ("resources/", "resources/")],
)
---
13.8 Errores Comunes al Exportar
| Error | Causa | Solución |
|---|---|---|
| ------- | ------- | ---------- |
| **"No se pudo abrir el archivo .ui"** | La ruta del archivo es incorrecta | Usa rutas relativas o absolutas correctas |
| **"No se encontró el widget"** | El nombre del widget no coincide | Verifica el `objectName` en Qt Designer |
| **"Error al cargar recursos"** | El archivo .qrc no está incluido | Empaqueta los recursos con la aplicación |
| **Los estilos no se aplican** | El styleSheet no se cargó correctamente | Verifica que el styleSheet esté en el .ui o cárgalo desde código |
| **Las conexiones no funcionan** | Los signals/slots no se configuraron bien | Verifica las conexiones en el .ui o conéctalas en código |
---
Ejercicio Práctico del Módulo
🏋️ EJERCICIO 13: Cargar tu Diseño en Python
>
Objetivo: Tomar un archivo .ui creado previamente y cargarlo con Python.
>
Pasos:
1. Toma cualquier archivo .ui que hayas creado en ejercicios anteriores
2. Crea un archivo
main.pyen la misma carpeta3. Escribe el código para cargar el .ui con QUiLoader (Método 1)
4. Ejecuta
python main.pyy verifica que la ventana se abre correctamente5. Ahora convierte el .ui con
pyside6-uic tu_archivo.ui -o ui_tu_archivo.py6. Modifica
main.pypara usar el archivo convertido (Método 2)7. Ejecuta nuevamente y verifica que funciona igual
8. Agrega una línea de código que cambie el texto de un Label al iniciar
9. Agrega una conexión de señal en Python para un botón
10. Experimenta con ambos métodos y decide cuál prefieres
>
Resultado esperado: Dos versiones funcionales de la misma interfaz, una cargando el .ui directamente y otra usando el archivo convertido.
---
Recursos Adicionales
| Recurso | Descripción |
|---|---|
| --------- | ------------- |
| [QUiLoader Documentation](https://doc.qt.io/qt-6/quiloader.html) | Documentación de QUiLoader |
| [pyside6-uic Documentation](https://doc.qt.io/qtforpython-6/overviews/uifiles.html) | Documentación de pyside6-uic |
| [PyInstaller Documentation](https://pyinstaller.org) | Documentación de PyInstaller |
| [Custom Widgets CLI](https://qtcustomwidgets.spinncode.com/API-Reference/CMD) | Herramientas de línea de comandos |
---
Evaluación de Comprensión
- ¿Qué formato tiene un archivo .ui?
- ¿Cuál es la ventaja principal del Método 1 (QUiLoader)?
- ¿Cuál es la ventaja principal del Método 2 (pyside6-uic)?
- ¿Qué comando convierte un .ui a Python?
- ¿Por qué NO debes editar manualmente el archivo .py generado?
- ¿Cómo accedes a un widget específico cuando usas QUiLoader?
- ¿Qué hace el comando
Custom_Widgets --monitor-ui? - ¿Cuál es la estructura de carpetas recomendada para un proyecto?
- ¿Cómo empaquetas una aplicación con PyInstaller incluyendo los archivos .ui?
- ¿Qué rol tiene el diseñador y qué rol tiene el programador en el flujo de trabajo?
---
Módulo anterior: ← [Módulo 12: Widgets Especializados](11-widgets-especializados.md)
Siguiente módulo: → [Módulo 14: Mejores Prácticas](13-mejores-practicas.md)
Escribe tus respuestas y luego presiona el botón para comparar con las respuestas correctas.