Módulo 5

Módulo 5: Layouts — El Arte de la Composición

El concepto más importante para crear interfaces profesionales y responsivas

El concepto más importante para crear interfaces profesionales y responsivas

---

Objetivos de Aprendizaje

Al finalizar este módulo serás capaz de:

  • Comprender qué son los layouts y por qué son absolutamente esenciales
  • Aplicar Vertical Layout, Horizontal Layout, Grid Layout y Form Layout
  • Combinar layouts anidados para crear interfaces complejas
  • Usar Spacers para controlar el espacio flexible
  • Configurar Size Policy para controlar el comportamiento de los widgets al redimensionar
  • Crear interfaces que se adaptan a cualquier tamaño de ventana
  • Identificar y corregir problemas comunes de layout

---

5.1 ¿Qué son los Layouts y por qué son CRUCIALES?

Los Layouts son reglas invisibles que controlan cómo se posicionan y redimensionan los widgets dentro de un contenedor. Son el concepto más importante que aprenderás en este curso.

🎨 ANALOGÍA DEL DISEÑO

>

Los Layouts son como las guías y cuadrículas (grids) que usas en InDesign o Figma. En lugar de colocar cada elemento pixel por pixel (posición absoluta), defines reglas de composición:

>

- "Este texto va arriba"

- "Estos botones van uno al lado del otro"

- "Esta imagen ocupa todo el espacio disponible"

>

Cuando el usuario redimensiona la ventana, todo se ajusta automáticamente.

El problema de NO usar layouts

Sin layouts, colocas widgets en posiciones fijas (posición absoluta). Esto causa problemas:

Problema Descripción
---------- -------------
**Se rompe al redimensionar** Si el usuario cambia el tamaño de la ventana, los widgets se quedan en su posición original
**Diferentes resoluciones** Tu diseño se ve perfecto en TU pantalla pero se ve mal en otras resoluciones
**Diferentes idiomas** Textos más largos en alemán que en español pueden salirse del espacio asignado
**Diferentes fuentes** Si el usuario cambia el tamaño de fuente del sistema, todo se desajusta

⚠️ IMPORTANTE

>

Sin Layouts, tu interfaz se rompe cuando el usuario cambia el tamaño de la ventana, usa una resolución diferente, o cambia el idioma. Siempre usa Layouts.

---

5.2 Vertical Layout (QVBoxLayout)

Apila los widgets uno encima del otro, de arriba hacia abajo.

Cómo aplicarlo

  1. Selecciona los widgets que quieres apilar (mantén presionado Ctrl y haz clic en cada uno)
  2. Haz clic en el botón Lay Out Vertically en la toolbar (o presiona Ctrl+L)
  3. Los widgets se apilan automáticamente con espaciado uniforme

Visualización

┌─────────────────────────┐
│  Widget 1 (arriba)      │
├─────────────────────────┤
│  Widget 2 (medio)       │
├─────────────────────────┤
│  Widget 3 (abajo)       │
└─────────────────────────┘

Propiedades del Layout Vertical

Propiedad Descripción Valor por defecto
----------- ------------- -------------------
**layoutSpacing** Espacio entre widgets (en píxeles) `6`
**layoutLeftMargin** Margen izquierdo `9`
**layoutRightMargin** Margen derecho `9`
**layoutTopMargin** Margen superior `9`
**layoutBottomMargin** Margen inferior `9`
**layoutStretch** Cómo se reparte el espacio extra `0,0,0` (igual para todos)

Cómo ajustar el espaciado

  1. Selecciona el contenedor que tiene el layout (no un widget individual)
  2. En el Property Editor, busca las propiedades que empiezan con layout...
  3. Cambia layoutSpacing para más o menos espacio entre widgets
  4. Cambia los márgenes para más o menos espacio en los bordes

---

5.3 Horizontal Layout (QHBoxLayout)

Coloca los widgets uno al lado del otro, de izquierda a derecha.

Cómo aplicarlo

  1. Selecciona los widgets
  2. Haz clic en Lay Out Horizontally (o presiona Ctrl+H)

Visualización

┌─────────────────────────────────────────────────┐
│ [Botón 1]  [Botón 2]  [Botón 3]                 │
└─────────────────────────────────────────────────┘

Cuándo usar Horizontal Layout

  • Barras de botones (Cancelar, Aceptar)
  • Label + campo de entrada en la misma línea
  • Iconos de toolbar
  • Elementos de navegación horizontal

🎨 ANALOGÍA DEL DISEÑO

>

Un Vertical Layout es como una columna en un periódico. Un Horizontal Layout es como los elementos de una barra de navegación.

---

5.4 Grid Layout (QGridLayout)

Organiza los widgets en una cuadrícula de filas y columnas. Es como una tabla de Excel donde cada celda puede contener un widget.

Cómo aplicarlo

  1. Selecciona los widgets
  2. Haz clic en Lay Out in a Grid (o presiona Ctrl+J)
  3. Los widgets se organizan en filas y columnas automáticamente según su posición actual

Visualización

┌──────────────────┬──────────────────┐
│  Fila 1, Col 1   │  Fila 1, Col 2   │
├──────────────────┼──────────────────┤
│  Fila 2, Col 1   │  Fila 2, Col 2   │
└──────────────────┴──────────────────┘

Cuándo usar Grid Layout

  • Formularios con labels a la izquierda y campos a la derecha
  • Galerías de imágenes en cuadrícula
  • Calculadoras (botones en filas y columnas)
  • Cualquier disposición que necesite alineación en dos dimensiones

💡 CONSEJO: El Grid Layout es perfecto para formularios donde tienes labels a la izquierda y campos de entrada a la derecha. Pero para ese caso específico, el Form Layout (siguiente sección) es aún mejor.

---

5.5 Form Layout (QFormLayout)

Especializado para formularios con etiquetas y campos. Crea automáticamente pares label-campo alineados profesionalmente.

Cómo aplicarlo

  1. Selecciona pares de widgets (label + campo de entrada)
  2. Haz clic en Lay Out in a Form Layout
  3. Las etiquetas se alinean automáticamente a la derecha y los campos a la izquierda

Visualización

┌─────────────────────────────────────────┐
│              Nombre: [____________]      │
│               Email: [____________]      │
│                 Edad: [____]             │
│               Ciudad: [____________]     │
└─────────────────────────────────────────┘

Propiedades del Form Layout

Propiedad Descripción Valores
----------- ------------- ---------
**labelAlignment** Alineación de las etiquetas `AlignLeft`, `AlignRight`
**formAlignment** Alineación del formulario completo `AlignTop`, `AlignBottom`, `AlignHCenter`, `AlignJustify`
**fieldGrowthPolicy** Cómo crecen los campos `AllNonFixedFieldsGrow`, `FieldsStayAtSizeHint`, `ExpandingFieldsGrow`
**rowWrapPolicy** Cuándo envolver filas `DontWrapRows`, `WrapLongRows`, `WrapAllRows`

🎨 ANALOGÍA DEL DISEÑO

>

El Form Layout es como usar las columnas guía de InDesign para alinear texto e imágenes perfectamente. Tú no calculas las posiciones: el layout lo hace por ti.

---

5.6 Layouts Anidados — La Clave del Diseño Profesional

El verdadero poder de los layouts viene cuando los combinas. Un layout puede contener otros layouts, creando estructuras complejas.

Ejemplo típico de una ventana profesional

┌─────────────────────────────────────────────────────┐
│  Layout Vertical (ocupa toda la ventana)            │
│  ┌───────────────────────────────────────────────┐  │
│  │  Label: "Registro de Usuario" (título)        │  │
│  ├───────────────────────────────────────────────┤  │
│  │  Layout Horizontal                            │  │
│  │  ┌─────────────────┐  ┌────────────────────┐  │  │
│  │  │ Layout Vertical │  │ Layout Vertical    │  │  │
│  │  │ (formulario)    │  │ (botones de acción)│  │  │
│  │  │ - Label + Input │  │ - Botón 1          │  │  │
│  │  │ - Label + Input │  │ - Botón 2          │  │  │
│  │  │ - Label + Input │  │ - Botón 3          │  │  │
│  │  └─────────────────┘  └────────────────────┘  │  │
│  ├───────────────────────────────────────────────┤  │
│  │  Layout Horizontal (botones inferiores)       │  │
│  │  [Spacer]           [Cancelar]  [Registrarse] │  │
│  └───────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘

Cómo crear layouts anidados

  1. Primero crea los layouts internos (los más pequeños)
  2. Luego crea los layouts externos que los contienen
  3. Los layouts se pueden arrastrar dentro de otros layouts

Paso a paso: Formulario con layouts anidados

Paso 1: Crea el Layout Vertical del formulario
┌─────────────────────┐
│ Label: "Nombre:"    │
│ Line Edit           │
│ Label: "Email:"     │
│ Line Edit           │
└─────────────────────┘

Paso 2: Crea el Layout Horizontal de botones
┌─────────────────────────────────┐
│ [Spacer]    [Cancelar] [OK]     │
└─────────────────────────────────┘

Paso 3: Combina ambos en un Layout Vertical principal
┌─────────────────────────────────┐
│ [Layout del formulario]         │
│                                 │
│ [Layout de botones]             │
└─────────────────────────────────┘

---

5.7 Spacers — El Espacio en Blanco

Horizontal Spacer y Vertical Spacer son widgets invisibles que empujan otros widgets. Son como el "espacio en blanco" en diseño gráfico: dan respiro y organización visual.

Cómo usar Spacers

  1. Arrastra un Spacer desde el Widget Box (categoría "Spacers")
  2. Colócalo dentro de un layout
  3. El Spacer ocupa todo el espacio disponible, empujando los demás widgets

Ejemplo: Botones alineados a la derecha

Sin Spacer:
┌─────────────────────────────────┐
│ [Cancelar]  [Aceptar]           │
└─────────────────────────────────┘

Con Horizontal Spacer:
┌─────────────────────────────────┐
│                [Cancelar][Aceptar]│
│  ←─── Spacer ocupa todo esto ───→│
└─────────────────────────────────┘

Ejemplo: Widget centrado

┌─────────────────────────────────┐
│ [Spacer]  [Widget]  [Spacer]    │
│  ←espacio→  ←fijo→  ←espacio→  │
└─────────────────────────────────┘

🎨 ANALOGÍA DEL DISEÑO

>

Los Spacers son como el margen automático en un diseño. En lugar de calcular manualmente cuánto espacio dejar, el Spacer "absorbe" todo el espacio sobrante y empuja los elementos hacia donde los necesitas.

---

5.8 Size Policy — Cómo los Widgets Deciden su Tamaño

Cada widget tiene una propiedad sizePolicy que controla cómo se comporta cuando el layout le da más o menos espacio del que pidió.

Políticas de Tamaño

Size Policy Comportamiento Horizontal Comportamiento Vertical Cuándo usar
------------- -------------------------- ------------------------ -------------
**Fixed** No crece ni encoge No crece ni encoge Botones, iconos, logos
**Minimum** Puede crecer si hay espacio Puede crecer si hay espacio Widgets que deben ser al menos de cierto tamaño
**Maximum** Puede encoger hasta su mínimo Puede encoger hasta su mínimo Widgets que no deben ser muy grandes
**Preferred** Tamaño ideal, pero puede ajustarse Tamaño ideal, pero puede ajustarse Labels, textos
**Expanding** Quiere todo el espacio posible Quiere todo el espacio posible Áreas de texto, listas, tablas
**MinimumExpanding** Crece para llenar espacio Crece para llenar espacio Similar a Expanding pero con mínimo garantizado
**Ignored** Ignora su sizeHint Ignora su sizeHint Raro, para casos especiales

Cómo cambiar el Size Policy

  1. Selecciona el widget
  2. En el Property Editor, busca sizePolicy
  3. Expande la propiedad para ver horizontalPolicy y verticalPolicy
  4. Cambia cada una independientemente

🎨 ANALOGÍA DEL DISEÑO

>

Piensa en Size Policy como la flexibilidad de un elemento en un diseño responsive:

>

- Un botón tiene size policy "Fixed" porque su tamaño no debe cambiar

- Un área de texto tiene "Expanding" porque debe ocupar todo el espacio disponible

- Es como definir si un elemento es "fluido" o "rígido" en tu maqueta

Ejemplo práctico de Size Policy

Ventana con un Text Edit que debe ocupar todo el espacio:

┌───────────────────────────────┐
│ Label: "Comentarios:"         │  ← sizePolicy: Preferred (tamaño natural)
├───────────────────────────────┤
│                               │
│                               │  ← Text Edit con sizePolicy: Expanding
│    (ocupa todo el espacio)    │     (crece para llenar el espacio disponible)
│                               │
│                               │
├───────────────────────────────┤
│          [Enviar] [Cancelar]   │  ← sizePolicy: Fixed (tamaño fijo)
└───────────────────────────────┘

---

5.9 layoutStretch — Controlar la Distribución del Espacio

La propiedad layoutStretch controla cómo se reparte el espacio extra entre los widgets de un layout.

Cómo funciona

Los valores son una lista de números separados por comas. Cada número representa la proporción de espacio que recibe ese widget.

Stretch values Resultado
---------------- -----------
`0,0,0` Todos reciben el mismo espacio extra (por defecto)
`1,2,1` El widget del medio recibe el doble de espacio
`0,1,0` Solo el widget del medio crece, los otros mantienen su tamaño
`3,1` El primer widget recibe 3 veces más espacio que el segundo

Cómo ajustar layoutStretch

  1. Selecciona el contenedor que tiene el layout
  2. En el Property Editor, busca layoutStretch
  3. Ingresa los valores separados por comas

Ejemplo: Sidebar + Contenido principal

Layout Horizontal con stretch "1,4":

┌──────┬────────────────────────────┐
│      │                            │
│  1   │            4               │
│      │                            │
│Sidebar│     Contenido principal    │
│      │                            │
└──────┴────────────────────────────┘

El contenido principal recibe 4 veces más espacio que el sidebar.

---

5.10 Romper un Layout

A veces necesitas deshacer un layout para reorganizar los widgets.

Cómo romper un layout

  1. Selecciona el contenedor que tiene el layout
  2. Haz clic en el botón Break Layout en la toolbar
  3. Los widgets quedan en sus posiciones actuales pero sin layout

💡 CONSEJO: Después de romper un layout, los widgets quedan en posiciones absolutas. No olvides aplicar un nuevo layout después de reorganizar.

---

5.11 Ajustar al Tamaño Ideal

El botón Adjust Size (Ctrl+0) redimensiona los widgets a su tamaño ideal (sizeHint).

Cuándo usarlo

  • Después de cambiar el texto de un widget y necesita más espacio
  • Para verificar que todos los widgets tienen el tamaño correcto
  • Antes de aplicar un layout, para asegurarte de que los widgets no están demasiado pequeños

---

5.12 Errores Comunes con Layouts

Error Problema Solución
------- ---------- ----------
**Widgets sin layout** Se desalinean al redimensionar Aplica siempre un layout al contenedor padre
**Layout applied to wrong widget** El layout no afecta a los widgets correctos Selecciona el contenedor padre antes de aplicar el layout
**Spacers olvidados** Los botones quedan a la izquierda en lugar de a la derecha Agrega un Horizontal Spacer antes de los botones
**Size Policy incorrecto** Un widget crece demasiado o no crece lo suficiente Ajusta el sizePolicy de cada widget
**layoutStretch no configurado** Todos los widgets crecen igual Configura layoutStretch para dar más espacio a los widgets que lo necesitan
**No probar al redimensionar** No sabes si funciona en otros tamaños Presiona `Ctrl+R` y redimensiona la ventana de vista previa

⚠️ IMPORTANTE

>

El error más común de los principiantes es colocar widgets "a ojo" sin layouts. Tu diseño se verá perfecto en TU pantalla, pero se romperá en cualquier otra resolución. Layouts desde el inicio, siempre.

---

5.13 Checklist de Layouts

Antes de considerar un diseño como terminado, verifica:

  • [ ] El widget/ventana principal tiene un layout aplicado
  • [ ] Todos los contenedores internos tienen layouts
  • [ ] Los Spacers están donde se necesita espacio flexible
  • [ ] Los widgets que deben crecer tienen sizePolicy Expanding
  • [ ] Los widgets que deben mantener su tamaño tienen sizePolicy Fixed
  • [ ] El layoutStretch está configurado para distribuir el espacio correctamente
  • [ ] La vista previa se ve bien al redimensionar la ventana
  • [ ] Los márgenes y espaciado son consistentes

---

Ejercicio Práctico del Módulo

🏋️ EJERCICIO 5: Formulario de Registro Profesional y Responsivo

>

Objetivo: Crear un formulario de registro que se adapte perfectamente a cualquier tamaño de ventana.

>

Pasos:

1. Crea un Dialog sin botones

2. Cambia el windowTitle a "Registro de Usuario"

3. Cambia el fondo: styleSheet: background-color: #1a1a2e;

4. Aplica un Layout Vertical al Dialog completo:

- Haz clic derecho en el Dialog (en el Object Inspector) > Lay Out > Lay Out Vertically

5. Agrega un Label de título: "Registro de Usuario" (fuente 20pt, blanco, centrado)

6. Agrega un Frame como contenedor del formulario:

- styleSheet: background-color: #2d2d3d; border-radius: 12px;

- Aplica un Layout Vertical al Frame

7. Dentro del Frame, agrega un Form Layout con:

- Label "Nombre:" + Line Edit (placeholder: "Tu nombre completo")

- Label "Email:" + Line Edit (placeholder: "tu@email.com")

- Label "País:" + Combo Box (agrega al menos 5 países)

- Label "Bio:" + Plain Text Edit (placeholder: "Cuéntanos sobre ti...")

8. Debajo del Frame, agrega un Horizontal Layout con:

- Horizontal Spacer (empuja los botones a la derecha)

- Push Button "Cancelar"

- Push Button "Registrarse" (estilizado con fondo verde)

9. Configura el sizePolicy del Plain Text Edit vertical a Expanding

10. Configura layoutStretch del Layout Vertical principal a 0,1,0

11. Renombra todos los widgets

12. Guarda como formulario_registro.ui

13. Presiona Ctrl+R y redimensiona la ventana para verificar que todo se adapta

>

Resultado esperado: Un formulario elegante que se redimensiona correctamente, con el área de bio creciendo y los botones siempre alineados a la derecha.

---

Recursos Adicionales

Recurso Descripción
--------- -------------
[Qt Layout Management](https://doc.qt.io/qt-6/layout.html) Documentación oficial sobre layouts
[QVBoxLayout](https://doc.qt.io/qt-6/qvboxlayout.html) Documentación de Vertical Layout
[QHBoxLayout](https://doc.qt.io/qt-6/qhboxlayout.html) Documentación de Horizontal Layout
[QGridLayout](https://doc.qt.io/qt-6/qgridlayout.html) Documentación de Grid Layout
[QFormLayout](https://doc.qt.io/qt-6/qformlayout.html) Documentación de Form Layout

---

Evaluación de Comprensión

  1. ¿Por qué es crucial usar layouts en lugar de posiciones fijas?
  2. ¿Cuál es la diferencia entre Vertical Layout y Horizontal Layout?
  3. ¿Cuándo usarías un Grid Layout y cuándo un Form Layout?
  4. ¿Qué hace un Horizontal Spacer?
  5. ¿Qué sizePolicy usarías para un Text Edit que debe ocupar todo el espacio disponible?
  6. ¿Qué significa layoutStretch "1,3,1"?
  7. ¿Cómo aplicas un layout a un contenedor?
  8. ¿Qué atajo de teclado aplica un Layout Vertical?
  9. ¿Qué propiedad controla el espacio entre widgets en un layout?
  10. ¿Cómo verificas que tu diseño funciona correctamente en diferentes tamaños?

---

Módulo anterior: ← [Módulo 4: Contenedores](03-contenedores.md)

Siguiente módulo: → [Módulo 6: Signals y Slots](05-signals-slots.md)

📝 Evaluación de Comprensión

Escribe tus respuestas y luego presiona el botón para comparar con las respuestas correctas.

1. ¿Por qué es crucial usar layouts en lugar de posiciones fijas?
✅ Respuesta Correcta
Porque sin layouts, la interfaz se rompe al redimensionar la ventana, se ve mal en diferentes resoluciones, idiomas con textos más largos, o diferentes tamaños de fuente del sistema. Los layouts hacen que todo se ajuste automáticamente.
2. ¿Cuál es la diferencia entre Vertical Layout y Horizontal Layout?
✅ Respuesta Correcta
Vertical Layout apila widgets uno encima del otro (de arriba hacia abajo). Horizontal Layout coloca widgets uno al lado del otro (de izquierda a derecha).
3. ¿Cuándo usarías un Grid Layout y cuándo un Form Layout?
✅ Respuesta Correcta
Grid Layout para organizar widgets en una cuadrícula de filas y columnas (calculadoras, galerías). Form Layout específicamente para formularios con pares label-campo, alineando automáticamente las etiquetas a la derecha y los campos a la izquierda.
4. ¿Qué hace un Horizontal Spacer?
✅ Respuesta Correcta
Es un widget invisible que ocupa todo el espacio disponible en un layout horizontal, empujando los demás widgets hacia un lado. Se usa como 'espacio en blanco' flexible.
5. ¿Qué sizePolicy usarías para un Text Edit que debe ocupar todo el espacio disponible?
✅ Respuesta Correcta
Expanding, porque quiere todo el espacio posible tanto horizontal como verticalmente.
6. ¿Qué significa layoutStretch '1,3,1'?
✅ Respuesta Correcta
Significa que el segundo widget recibe 3 veces más espacio extra que el primero y el tercero. El widget del medio crece proporcionalmente más que los laterales.
7. ¿Cómo aplicas un layout a un contenedor?
✅ Respuesta Correcta
Seleccionando el contenedor y haciendo clic en el botón de layout correspondiente en la toolbar, o clic derecho > Lay Out > seleccionando el tipo de layout, o usando atajos como Ctrl+L (vertical), Ctrl+H (horizontal), Ctrl+J (grid).
8. ¿Qué atajo de teclado aplica un Layout Vertical?
✅ Respuesta Correcta
Ctrl+L
9. ¿Qué propiedad controla el espacio entre widgets en un layout?
✅ Respuesta Correcta
layoutSpacing
10. ¿Cómo verificas que tu diseño funciona correctamente en diferentes tamaños?
✅ Respuesta Correcta
Presionando Ctrl+R para ver la vista previa y redimensionando la ventana de vista previa para verificar que todo se adapta correctamente.
🏋️ Ejercicio Práctico

Ejercicio 5: Formulario de Registro Responsivo

Módulo 5: Layouts

---

Objetivo

Crear un formulario de registro profesional y completamente responsivo.

---

Instrucciones

  1. Crea un Dialog sin botones
  2. windowTitle: "Registro de Usuario"
  3. Fondo: styleSheet: background-color: #1a1a2e;
  4. Aplica un Layout Vertical al Dialog completo:
  • Clic derecho en el Dialog (Object Inspector) > Lay Out > Lay Out Vertically
  1. Label de título: "Registro de Usuario" (20pt, blanco, centrado)
  2. Frame como contenedor del formulario:
  • styleSheet: background-color: #2d2d3d; border-radius: 12px;
  • Aplica un Layout Vertical al Frame
  1. Dentro del Frame, Form Layout con:
  • Label "Nombre:" + Line Edit (placeholder: "Tu nombre completo")
  • Label "Email:" + Line Edit (placeholder: "tu@email.com")
  • Label "País:" + Combo Box (al menos 5 países)
  • Label "Bio:" + Plain Text Edit (placeholder: "Cuéntanos sobre ti...")
  1. Debajo del Frame, Horizontal Layout con:
  • Horizontal Spacer (empuja botones a la derecha)
  • Push Button "Cancelar"
  • Push Button "Registrarse" (estilizado en verde)
  1. Configura el sizePolicy del Plain Text Edit vertical a Expanding
  2. Configura layoutStretch del Layout Vertical principal a 0,1,0
  3. Renombra todos los widgets
  4. Guarda como formulario_registro.ui
  5. Presiona Ctrl+R y redimensiona la ventana para verificar que todo se adapta

---

Resultado Esperado

Un formulario elegante que se redimensiona correctamente, con el área de bio creciendo y los botones siempre alineados a la derecha.

---

Checklist

  • [ ] Layout Vertical aplicado al Dialog
  • [ ] Label de título centrado
  • [ ] Frame con estilo de tarjeta
  • [ ] Form Layout con 4 campos
  • [ ] Horizontal Layout con Spacer + 2 botones
  • [ ] Plain Text Edit con sizePolicy Expanding
  • [ ] layoutStretch configurado a 0,1,0
  • [ ] Se adapta correctamente al redimensionar