En Qt, un evento es un objeto que hereda de QEvent. Los tipos comunes incluyen QKeyEvent para teclado, QMouseEvent para ratón y QTimerEvent para temporizadores. Es crucial distinguir entre eventos y señales: provienen de fuentes ditsintas y cumplen propósitos diferentes.
Enfoques para Procesar Eventos
Existen cinco estrategias principales:
- Sobreescribir métodos específicos del widget, como
paintEvent()omousePressEvent(). Este método solo aplica a un evento concreto de una clase específica. - Reimplementar la función
notify(), que ofrece control total y permite interceptar eventos antes de los filtros, pero está limitada a procesar un evento cada vez. - Instalar un filtro de eventos en el objeto
QApplication, lo que facilita el manejo de múltiples eventos de manera centralizada. - Reimplementar la función
event()deQObject, la cual intercepta eventos antes de que lleguen a los manejadores predeterminados. - Instalar filtros de eventos en objetos individuales.
Propagación de Eventos
La ejecución de exec() en main() inicia el bucle de eventos de Qt. Cuando ocurre un evento, Qt construye un objeto de la subclase correspondiente de QEvent y lo dirige al QObject apropiado.
Si el widget objetivo ignora el evento, este se propaga a su widget padre. El siugiente código muestra una tecla presionada que es ignorada por una subclase personalizada de QLineEdit:
void EditorPersonalizado::keyPressEvent(QKeyEvent *eventoTecla)
{
qDebug() << "Evento de tecla detectado en EditorPersonalizado";
QLineEdit::keyPressEvent(eventoTecla); // Manejo base
eventoTecla->ignore(); // Se marca como ignorado
}
El siguiente diagrama ilustra una secuencia alternativa de propagación:
- Filtro de eventos instalado.
- Método
event()del widget con foco. - Manejador específico del widget (ej.
keyPressEvent()). - Si se ignora, el manejador del widget padre.
Ejemplo de reimplementación de event():
bool EditorConFoco::event(QEvent *evento)
{
if (evento->type() == QEvent::KeyPress)
{
qDebug() << "Interceptado en event() de EditorConFoco";
}
return QLineEdit::event(evento); // Llama al comportamiento base
}
Para instalar un filtro de eventos en un widget específico:
// En el constructor del widget contenedor:
editorObjetivo->installEventFilter(this);
// Implementación del filtro:
bool WidgetContenedor::eventFilter(QObject *objetoObservado, QEvent *evento)
{
if (objetoObservado == editorObjetivo && evento->type() == QEvent::KeyPress)
{
qDebug() << "Filtro activado para editorObjetivo";
}
return QWidget::eventFilter(objetoObservado, evento);
}
Eventos de Ratón y Rueda
QMouseEvent proporciona datos sobre qué botón se pulsó y la posición del cursor. QWheelEvent captura el desplazamiento y dirección de la rueda del ratón.
Eventos de Teclado
QKeyEvent identifica la tecla mediante key() (ver Qt::Key en la documentación). Las teclas modificadoras (Ctrl, Shift) se obtienen con modifiers().
void WidgetPrincipal::keyPressEvent(QKeyEvent *eventoTecla)
{
if (eventoTecla->modifiers() == Qt::ControlModifier && eventoTecla->key() == Qt::Key_P)
{
mostrarPanelPreferencias(); // Acción personalizada
}
else
{
QWidget::keyPressEvent(eventoTecla);
}
}
Eventos de Temporización
QTimer emite señales periódicas. Ejemplo de un reloj digital que alterna el separador cada segundo:
// Inicialización en el constructor
temporizadorReloj = new QTimer(this);
connect(temporizadorReloj, &QTimer::timeout, this, &WidgetReloj::actualizarVisual);
temporizadorReloj->start(1000); // Intervalo de 1 segundo
// Slot privado
void WidgetReloj::actualizarVisual()
{
QTime horaActual = QTime::currentTime();
QString formato = horaActual.toString("hh:mm");
if (horaActual.second() % 2 == 0)
{
formato[2] = ' '; // Oculta el separador alternando
}
pantallaLCD->display(formato);
}
Filtros de Eventos
Este mecanismo permite interceptar eventos destinados a otros objetos. Se configura mediante installEventFilter() y la reimplementación de eventFilter().