Módulo 6: Signals y Slots — Dando Vida a tu Diseño
Conecta elementos para que respondan a las acciones del usuario, sin programar
Conecta elementos para que respondan a las acciones del usuario, sin programar
---
Objetivos de Aprendizaje
Al finalizar este módulo serás capaz de:
- Comprender qué son Signals y Slots y cómo funcionan
- Usar el Signal/Slot Editor de Qt Designer para crear conexiones visuales
- Conectar los signals y slots más comunes entre widgets
- Crear interfaces interactivas sin escribir una sola línea de código
- Entender el flujo de datos entre widgets conectados
- Identificar qué conexiones son posibles y cuáles requieren código
---
6.1 ¿Qué son Signals y Slots?
Signals (señales) son eventos que un widget emite cuando algo sucede.
Slots (ranuras) son acciones que otro widget ejecuta como respuesta.
🎨 ANALOGÍA DEL DISEÑO
>
En diseño gráfico, cuando haces un prototipo interactivo en Figma, conectas un botón con una pantalla: "cuando el usuario hace clic aquí, muestra esta pantalla".
>
Signals y Slots son exactamente eso: "CUANDO pasa esto (signal), ENTONCES haz esto (slot)".
>
Ejemplo: "CUANDO el usuario hace clic en el botón (signal: clicked), ENTONCES cierra la ventana (slot: close)".
El concepto en una frase
CUANDO [widget A] hace [signal] → ENTONCES [widget B] ejecuta [slot]
Ejemplos cotidianos
| CUANDO (Signal) | ENTONCES (Slot) | Resultado |
|---|---|---|
| ----------------- | ----------------- | ----------- |
| Usuario hace clic en botón (`clicked`) | Ventana se cierra (`close`) | El botón cierra la ventana |
| Usuario escribe en campo (`textChanged`) | Label actualiza su texto (`setText`) | El label muestra lo que escribes |
| Usuario mueve slider (`valueChanged`) | Spin Box cambia valor (`setValue`) | El spin box sigue al slider |
| Usuario marca checkbox (`toggled`) | Frame se muestra/oculta (`setVisible`) | El checkbox muestra/oculta contenido |
💡 CONSEJO: Lo mejor es que puedes configurar Signals y Slots directamente en Qt Designer, sin escribir una sola línea de código.
---
6.2 El Signal/Slot Editor
En la parte inferior de Qt Designer hay una pestaña llamada "Signals & Slots Editor". Aquí defines las conexiones de forma visual.
Modo Edición de Signals/Slots (F4)
- Presiona F4 o haz clic en el botón "Edit Signals/Slots" en la toolbar
- El cursor cambia a una flecha con un rayo ⚡
- Haz clic en un widget (el que emite la señal) y arrastra hacia otro widget (el que responde)
- Aparecerá un diálogo donde seleccionas:
- Signal: qué evento dispara la acción (clicked, textChanged, valueChanged, etc.)
- Slot: qué acción se ejecuta (close, setText, hide, show, etc.)
- Haz clic en OK y la conexión queda creada
- Presiona F3 para volver al modo normal de edición
📸 [PLACEHOLDER PARA IMAGEN]: Captura de pantalla mostrando el modo F4 con una línea roja conectando un botón con un diálogo, y el diálogo de configuración de signal/slot.
Cómo ver las conexiones existentes
En modo F4, las conexiones se muestran como líneas rojas entre los widgets conectados. También puedes verlas en la pestaña "Signals & Slots Editor" en la parte inferior de la ventana.
Cómo eliminar una conexión
- Ve a la pestaña "Signals & Slots Editor" (parte inferior)
- Selecciona la conexión que quieres eliminar
- Presiona Delete o haz clic en el botón de eliminar
---
6.3 Conexiones Comunes sin Código
Estas son las conexiones más útiles que puedes hacer completamente en Qt Designer:
Cerrar ventana con botón
| Origen | Signal | Destino | Slot |
|---|---|---|---|
| -------- | -------- | --------- | ------ |
| Push Button | `clicked()` | Dialog / MainWindow | `close()` |
Resultado: Al hacer clic en el botón, la ventana se cierra.
Ocultar widget con botón
| Origen | Signal | Destino | Slot |
|---|---|---|---|
| -------- | -------- | --------- | ------ |
| Push Button | `clicked()` | Label / Frame / Widget | `hide()` |
Resultado: Al hacer clic, el widget desaparece.
Mostrar texto mientras escribes
| Origen | Signal | Destino | Slot |
|---|---|---|---|
| -------- | -------- | --------- | ------ |
| Line Edit | `textChanged(QString)` | Label | `setText(QString)` |
Resultado: El Label muestra en tiempo real lo que escribes en el Line Edit.
Slider sincronizado con Spin Box
| Origen | Signal | Destino | Slot |
|---|---|---|---|
| -------- | -------- | --------- | ------ |
| Slider | `valueChanged(int)` | Spin Box | `setValue(int)` |
| Spin Box | `valueChanged(int)` | Slider | `setValue(int)` |
Resultado: El slider y el spin box se mantienen sincronizados. Mueve uno y el otro sigue.
Checkbox muestra/oculta contenido
| Origen | Signal | Destino | Slot |
|---|---|---|---|
| -------- | -------- | --------- | ------ |
| Check Box | `toggled(bool)` | Frame / Widget | `setVisible(bool)` |
Resultado: Cuando marcas el checkbox, el contenido aparece. Cuando lo desmarcas, desaparece.
Radio Button muestra/oculta sección
| Origen | Signal | Destino | Slot |
|---|---|---|---|
| -------- | -------- | --------- | ------ |
| Radio Button | `toggled(bool)` | Frame / Group Box | `setVisible(bool)` |
Resultado: Seleccionar un radio button muestra una sección específica.
Progreso controlado por slider
| Origen | Signal | Destino | Slot |
|---|---|---|---|
| -------- | -------- | --------- | ------ |
| Slider | `valueChanged(int)` | Progress Bar | `setValue(int)` |
| Slider | `valueChanged(int)` | LCD Number | `display(int)` |
Resultado: El slider controla tanto la barra de progreso como el display numérico.
Cambiar pestaña con botón
| Origen | Signal | Destino | Slot |
|---|---|---|---|
| -------- | -------- | --------- | ------ |
| Push Button | `clicked()` | Tab Widget | `setCurrentIndex(int)` |
💡 CONSEJO: Para usar
setCurrentIndex(int), necesitas editar la conexión y especificar el valor del índice manualmente. Qt Designer te pedirá el valor numérico.
---
6.4 Signals Más Útiles por Widget
Push Button
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `clicked()` | Al hacer clic en el botón |
| `pressed()` | Al presionar el botón (antes de soltar) |
| `released()` | Al soltar el botón |
Check Box
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `toggled(bool)` | Al cambiar su estado (marcado/desmarcado) |
| `stateChanged(int)` | Al cambiar su estado (con valor numérico: 0=desmarcado, 2=marcado) |
Radio Button
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `toggled(bool)` | Al cambiar su estado |
| `clicked()` | Al hacer clic |
Line Edit
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `textChanged(QString)` | Cada vez que cambia el texto (mientras escribes) |
| `editingFinished()` | Cuando terminas de editar (presionas Enter o pierdes el foco) |
| `returnPressed()` | Cuando presionas Enter |
Combo Box
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `currentIndexChanged(int)` | Al cambiar la selección (por índice) |
| `currentTextChanged(QString)` | Al cambiar la selección (por texto) |
| `activated(int)` | Al seleccionar un item (incluso si ya estaba seleccionado) |
Slider
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `valueChanged(int)` | Al cambiar el valor |
| `sliderMoved(int)` | Al arrastrar el slider (no al hacer clic en la barra) |
| `sliderPressed()` | Al empezar a arrastrar |
| `sliderReleased()` | Al soltar |
Spin Box / Double Spin Box
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `valueChanged(int)` | Al cambiar el valor |
| `valueChanged(double)` | Al cambiar el valor (Double Spin Box) |
Tab Widget
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `currentChanged(int)` | Al cambiar de pestaña |
Date Edit / Time Edit
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `dateChanged(QDate)` | Al cambiar la fecha |
| `timeChanged(QTime)` | Al cambiar la hora |
Calendar Widget
| Signal | Cuándo se dispara |
|---|---|
| -------- | ------------------- |
| `selectionChanged()` | Al seleccionar una fecha diferente |
| `clicked(QDate)` | Al hacer clic en una fecha |
---
6.5 Slots Más Útiles por Widget
Cualquier Widget
| Slot | Qué hace |
|---|---|
| ------ | ---------- |
| `close()` | Cierra la ventana/widget |
| `hide()` | Oculta el widget |
| `show()` | Muestra el widget (si estaba oculto) |
| `setEnabled(bool)` | Activa/desactiva el widget |
| `setVisible(bool)` | Muestra/oculta según el valor booleano |
Label
| Slot | Qué hace |
|---|---|
| ------ | ---------- |
| `setText(QString)` | Cambia el texto del Label |
| `clear()` | Limpia el texto del Label |
Line Edit
| Slot | Qué hace |
|---|---|
| ------ | ---------- |
| `setText(QString)` | Cambia el texto del campo |
| `clear()` | Limpia el campo |
Text Edit / Plain Text Edit
| Slot | Qué hace |
|---|---|
| ------ | ---------- |
| `setText(QString)` | Cambia el texto |
| `clear()` | Limpia el texto |
| `append(QString)` | Agrega texto al final |
Slider / Spin Box / Progress Bar
| Slot | Qué hace |
|---|---|
| ------ | ---------- |
| `setValue(int)` | Cambia el valor |
| `reset()` | Reinicia al valor mínimo |
LCD Number
| Slot | Qué hace |
|---|---|
| ------ | ---------- |
| `display(int)` | Muestra un número entero |
| `display(double)` | Muestra un número decimal |
| `display(QString)` | Muestra un texto |
Combo Box
| Slot | Qué hace |
|---|---|
| ------ | ---------- |
| `setCurrentIndex(int)` | Selecciona un item por índice |
| `clear()` | Elimina todos los items |
---
6.6 Tipos de Datos en Signals y Slots
Para que una conexión funcione, los tipos de datos del signal y el slot deben ser compatibles:
| Tipo de dato | Descripción | Ejemplo de uso |
|---|---|---|
| -------------- | ------------- | ---------------- |
| **Sin tipo** `()` | No lleva datos | `clicked()`, `close()` |
| **bool** | Verdadero o falso | `toggled(bool)` → `setVisible(bool)` |
| **int** | Número entero | `valueChanged(int)` → `setValue(int)` |
| **QString** | Texto | `textChanged(QString)` → `setText(QString)` |
| **double** | Número decimal | `valueChanged(double)` → `display(double)` |
⚠️ IMPORTANTE
>
No puedes conectar un signal que envía un tipo de dato con un slot que espera otro tipo diferente. Por ejemplo, no puedes conectar
textChanged(QString)consetValue(int)directamente.
---
6.7 Conexiones en el Signals & Slots Editor
Además del modo visual (F4), puedes usar la pestaña Signals & Slots Editor en la parte inferior:
| Columna | Descripción |
|---|---|
| --------- | ------------- |
| **Sender** | El widget que emite la señal |
| **Signal** | La señal que emite |
| **Receiver** | El widget que recibe la señal |
| **Slot** | La acción que ejecuta |
Cómo agregar una conexión desde el editor
- Haz clic en el botón "+" del Signals & Slots Editor
- Selecciona el Sender (widget origen)
- Selecciona el Signal
- Selecciona el Receiver (widget destino)
- Selecciona el Slot
- Haz clic en OK
---
6.8 Editar Conexiones con Valores Personalizados
Algunos slots requieren un valor específico. Por ejemplo, setCurrentIndex(int) necesita saber qué índice establecer.
Cómo editar una conexión existente
- En el Signals & Slots Editor, haz doble clic en la conexión
- O haz clic derecho > Edit
- En el diálogo, puedes:
- Cambiar el signal
- Cambiar el slot
- Editar el valor del argumento (para slots que requieren un valor específico)
Ejemplo: Botón que cambia a la pestaña 2
- Conecta: Push Button (
clicked()) → Tab Widget - En el slot, selecciona
setCurrentIndex(int) - Qt Designer te pedirá el valor: ingresa
1(los índices empiezan en 0, así que 1 = segunda pestaña)
---
6.9 Limitaciones de Signals/Slots en Qt Designer
No todas las conexiones son posibles sin código. Estas son las limitaciones:
| Lo que SÍ puedes hacer | Lo que NO puedes hacer sin código |
|---|---|
| ------------------------ | ----------------------------------- |
| Conectar signals existentes a slots existentes | Crear signals o slots personalizados |
| Pasar valores simples (int, bool, QString) | Ejecutar lógica compleja (cálculos, condiciones) |
| Mostrar/ocultar widgets | Validar datos de entrada |
| Cambiar texto de widgets | Guardar datos en archivos o bases de datos |
| Cambiar valores numéricos | Hacer peticiones a internet |
| Cerrar ventanas | Abrir otras ventanas |
💡 CONSEJO: Para funcionalidad avanzada, necesitarás código Python. Pero el 80% de las interacciones básicas se pueden configurar sin código en Qt Designer.
---
6.10 Flujo de Datos Visual
Así es como funciona el flujo de datos entre widgets conectados:
Usuario escribe "Hola" en Line Edit
│
▼
Line Edit emite: textChanged("Hola")
│
▼ (conexión configurada)
Label recibe: setText("Hola")
│
▼
Label muestra: "Hola"
Usuario mueve Slider a valor 75
│
▼
Slider emite: valueChanged(75)
│
▼ (conexión configurada)
Progress Bar recibe: setValue(75)
│
▼
Progress Bar muestra: 75%
---
Ejercicio Práctico del Módulo
🏋️ EJERCICIO 6: Mini Aplicación Interactiva sin Código
>
Objetivo: Crear una interfaz completamente interactiva usando solo Signals y Slots de Qt Designer.
>
Pasos:
1. Crea un Dialog sin botones de 500x400 píxeles
2. Cambia el
windowTitlea "Demo Interactiva"3. Cambia el fondo:
styleSheet: background-color: #1a1a2e;4. Agrega un Label de título: "Escribe algo:" (fuente 16pt, blanco)
5. Agrega un Line Edit con placeholder "Escribe algo aquí..."
6. Agrega un Label debajo con texto "Tu texto aparecerá aquí" (fuente 14pt, color verde, centrado)
7. Conecta: Line Edit (
textChanged) → Label (setText)8. Agrega un Label con texto "Control de volumen:"
9. Agrega un Horizontal Slider (min: 0, max: 100, value: 50)
10. Agrega un Spin Box al lado del slider (min: 0, max: 100, value: 50)
11. Agrega un Progress Bar debajo (min: 0, max: 100, value: 50, textVisible: true)
12. Agrega un LCD Number al lado del Progress Bar (digitCount: 3, value: 50)
13. Conecta: Slider (
valueChanged) → Spin Box (setValue)14. Conecta: Spin Box (
valueChanged) → Slider (setValue)15. Conecta: Slider (
valueChanged) → Progress Bar (setValue)16. Conecta: Slider (
valueChanged) → LCD Number (display)17. Agrega un Check Box con texto "Mostrar controles avanzados"
18. Agrega un Frame con un Dial y un Double Spin Box dentro (controles avanzados)
19. Conecta: Check Box (
toggled) → Frame (setVisible)20. Agrega un Push Button con texto "Cerrar" (estilizado en rojo)
21. Conecta: Button (
clicked) → Dialog (close)22. Renombra todos los widgets
23. Guarda como
demo_interactiva.ui24. Presiona
Ctrl+Ry prueba TODAS las interacciones
>
Resultado esperado: Una interfaz donde todo responde al usuario: el texto se replica, el slider controla múltiples widgets, el checkbox muestra/oculta contenido, y el botón cierra la ventana. Todo sin una sola línea de código.
---
Recursos Adicionales
| Recurso | Descripción |
|---|---|
| --------- | ------------- |
| [Signals and Slots](https://doc.qt.io/qt-6/signalsandslots.html) | Documentación oficial |
| [Qt Designer Signals/Slots](https://doc.qt.io/qt-6/designer-connection.html) | Cómo usar signals/slots en Qt Designer |
| [Qt Signals and Slots Tutorial](https://doc.qt.io/qt-6/signalsandslots-tutorial.html) | Tutorial paso a paso |
---
Evaluación de Comprensión
- ¿Qué es un Signal y qué es un Slot? Explica con tus propias palabras.
- ¿Cómo entras al modo de edición de Signals/Slots en Qt Designer?
- ¿Qué connection harías para que un botón cierre la ventana?
- ¿Qué signal del Line Edit se dispara mientras escribes (no al terminar)?
- ¿Cómo sincronizas un Slider con un Spin Box para que se muevan juntos?
- ¿Qué slot usarías para ocultar un Frame cuando se desmarca un Check Box?
- ¿Por qué no puedes conectar
textChanged(QString)consetValue(int)? - ¿Qué significa que un slot requiere un valor como
setCurrentIndex(1)? - ¿Dónde puedes ver todas las conexiones que has creado?
- ¿Qué limitaciones tienen los Signals/Slots configurados en Qt Designer?
---
Módulo anterior: ← [Módulo 5: Layouts](04-layouts.md)
Siguiente módulo: → [Módulo 7: Propiedades Avanzadas](06-propiedades-avanzadas.md)
Escribe tus respuestas y luego presiona el botón para comparar con las respuestas correctas.
Ejercicio 6: Mini Aplicación Interactiva sin Código
Módulo 6: Signals y Slots
---
Objetivo
Crear una interfaz completamente interactiva usando solo Signals y Slots de Qt Designer.
---
Instrucciones
- Crea un Dialog sin botones de 500x400 píxeles
windowTitle: "Demo Interactiva"- Fondo:
styleSheet: background-color: #1a1a2e; - Label título: "Escribe algo:" (16pt, blanco)
- Line Edit con placeholder "Escribe algo aquí..."
- Label debajo con texto "Tu texto aparecerá aquí" (14pt, verde, centrado)
- Conecta (F4): Line Edit (
textChanged) → Label (setText) - Label: "Control de volumen:"
- Horizontal Slider (min: 0, max: 100, value: 50)
- Spin Box al lado del slider (min: 0, max: 100, value: 50)
- Progress Bar debajo (min: 0, max: 100, value: 50, textVisible: true)
- LCD Number al lado del Progress Bar (digitCount: 3, value: 50)
- Conecta: Slider (
valueChanged) → Spin Box (setValue) - Conecta: Spin Box (
valueChanged) → Slider (setValue) - Conecta: Slider (
valueChanged) → Progress Bar (setValue) - Conecta: Slider (
valueChanged) → LCD Number (display) - Check Box: "Mostrar controles avanzados"
- Frame con un Dial y un Double Spin Box dentro
- Conecta: Check Box (
toggled) → Frame (setVisible) - Push Button "Cerrar" (estilizado en rojo)
- Conecta: Button (
clicked) → Dialog (close) - Renombra todos los widgets
- Guarda como
demo_interactiva.ui - Presiona
Ctrl+Ry prueba TODAS las interacciones
---
Resultado Esperado
Una interfaz donde todo responde al usuario: el texto se replica en el label, el slider controla el spin box, progress bar y LCD number simultáneamente, el checkbox muestra/oculta el frame con controles avanzados, y el botón cierra la ventana. Todo sin código.
---
Checklist
- [ ] Line Edit → Label (text se replica en tiempo real)
- [ ] Slider ↔ Spin Box (sincronizados bidireccionalmente)
- [ ] Slider → Progress Bar (muestra el valor)
- [ ] Slider → LCD Number (muestra el valor)
- [ ] Check Box → Frame (muestra/oculta controles avanzados)
- [ ] Botón Cerrar → Dialog (cierra la ventana)
- [ ] Todas las conexiones visibles en modo F4