¿Cómo implemento QHoverEvent en Qt?
Pregunta
Estoy aprendiendo Qt con C ++. He implementado con éxito señales y ranuras para atrapar eventos estándar como ButtonPushed ()
, etc. Sin embargo, quiero tener una función llamada cuando muevo el mouse sobre y el mouse fuera de un QLabel
. Parece que QHoverEvent hará lo que necesito, pero no puedo para encontrar tutoriales o ejemplos sobre cómo implementar esto. ¿Se hace de la misma manera que las señales y las ranuras? Lo intenté:
connect(ui.lbl_test, SIGNAL(QHoverEvent), this, SLOT(TestFunc(QEvent::Type type, const QPoint & pos, const QPoint & oldPos)));
.. pero la función no fue llamada cuando me coloqué sobre la etiqueta.
Aquí está la función, listada en el archivo de encabezado como espacio público:
void MyDialog::TestFunc(QEvent::Type type, const QPoint & pos, const QPoint & oldPos) {
QMessageBox::information(this, tr("Hey"), tr("Listen!"));
}
¿Puede alguien ayudarme a resolver esto o señalarme un buen ejemplo?
EDITAR:
Después de leer una publicación a continuación, no encontré ningún miembro de setFlag ()
para llamar a mi widget de etiqueta, pero lo intenté:
ui.lbl_test->setMouseTracking(true);
connect(ui.lbl_test, SIGNAL(ui.lbl_test->mouseMoveEvent()), this, SLOT(TestFunc(QMouseEvent *event)));
Y actualizado TestFunc ()
en consecuencia. Pero aún así no pasa nada cuando muevo el mouse.
Después de mirar, no estoy seguro de que QLabel
incluso herede el mouseMoveEvent () incluso de QWidget
. Si esto es cierto, ¿existe un widget que lo haga o una lista de objetos que lo heredan en algún lugar? Todo lo que puedo decir de la documentación de su sitio es cuántas funciones heredadas tiene un objeto ...
Solución
El uso de señales y ranuras para este propósito no va a funcionar.
mouseMoveEvent ()
no es una señal ni un meta-método y no se puede conectar a una ranura.
Subclasificar la clase de widget e invalidar mouseMoveEvent ()
le permitirá obtener eventos de movimiento de mouse, pero esa es una forma muy pesada de lograr esto (y agrega una clase más a su base de origen ).
En su lugar, considere implementar un método eventFilter ()
en su clase MyDialog
e instálelo en el QLabel
. Con este método de filtro de eventos, puede interceptar todos los eventos para una instancia de QObject
dada.
Aquí está la documentación sobre los filtros de eventos.
http://doc.qt.io/qt-4.8 /eventsandfilters.html#event-filters
Además, al observar el ejemplo del código, le recomiendo que se tome un momento para investigar qué hacen las macros SIGNAL ()
y SLOT ()
. Puede ver cómo se definen en $QTDIR/src/corelib/kernel/qobjectdefs.h
Otros consejos
Según el enlace del documento que proporcionas, solo obtendrás este QHoverEvent si tu widget tiene el indicador Qt :: WA_Hover
.
Después de construir la llamada al widget:
widget->setAttribute(Qt::WA_Hover);
y ver si funciona.
Otra forma de lograr el mismo resultado es anular mouseMoveEvent ()
en tu widget
Tenga en cuenta que esta función tampoco se llamará normalmente a menos que llame:
widget->setMouseTracking(true);
Esta es básicamente la manera en que QT implementa el evento de desplazamiento interno.
http://qt-project.org/doc/qt -5 / qwidget.html # enterEvent
http://qt-project.org/doc/qt -5 / qwidget.html # leaveEvent
http://qt-project.org/doc /qt-5/qt.html#widget-attributes
Qt :: WA_Hover
Obliga a Qt a generar eventos de pintura cuando el mouse entra o sale del widget Esta característica se usa normalmente cuando se implementa personalizado estilos; vea el ejemplo de Estilos para más detalles.
Esta sobrecarga de
QStyle :: polish ()
se llama una vez en cada widget dibujado usando el estilo. Lo reimplementamos para establecer el atributoQt :: WA_Hover
enQPushButtons
yQComboBoxes
. Cuando se establece este atributo, Qt genera eventos de pintura cuando el puntero del mouse entra o sale de la widget Esto hace posible renderizar pulsadores y comboboxes. diferente cuando el puntero del mouse está sobre ellos.
Cómo recibir eventos de entrada y salida en un QWidget
-
Establezca el atributo del widget para WA_Hover
// in your widget's constructor (probably) this->setAttribute(Qt::WA_HOVER, true);
-
Implemente
QWidget :: enterEvent ()
yQWidget :: leaveEvent ()
.void Widget::enterEvent(QEvent * event) { qDebug() << Q_FUNC_INFO << this->objectName(); QWidget::enterEvent(event); } void Widget::leaveEvent(QEvent * event) { qDebug() << Q_FUNC_INFO << this->objectName(); QWidget::leaveEvent(event); }
Listo
QHoverEvent en QWidget
http://qt-project.org/doc/qt -5 / qhoverevent.html # detalles
http://qt-project.org/doc/qt -5 / qobject.html # evento
http://qt-project.org/doc/qt -5 / qwidget.html # evento
// in your widget's constructor (probably)
this->setAttribute(Qt::WA_HOVER, true);
// ...
void Widget::hoverEnter(QHoverEvent * event) {qDebug() << Q_FUNC_INFO << this->objectName();}
void Widget::hoverLeave(QHoverEvent * event) {qDebug() << Q_FUNC_INFO << this->objectName();}
void Widget::hoverMove(QHoverEvent * event) {qDebug() << Q_FUNC_INFO << this->objectName();}
bool Widget::event(QEvent * e)
{
switch(e->type())
{
case QEvent::HoverEnter:
hoverEnter(static_cast<QHoverEvent*>(e));
return true;
break;
case QEvent::HoverLeave:
hoverLeave(static_cast<QHoverEvent*>(e));
return true;
break;
case QEvent::HoverMove:
hoverMove(static_cast<QHoverEvent*>(e));
return true;
break;
default:
break;
}
return QWidget::event(e);
}
ACTUALIZAR:
Ejemplo simple
Mueve el botón y ve el cambio de cuenta. Mire la salida de la aplicación para obtener más información.
Tenía el mismo problema, llegué al siguiente diseño de solución:
En mi widget principal, me gustaría procesar eventos de desplazamiento de algunos objetos seleccionados. Por este motivo, creé 2 ranuras en mi MainWindow
:
public slots:
void onHoverIn(QObject* object);
void onHoverOut(QObject* object);
Luego creé una clase de filtro de eventos como esta:
hovereventfilter.h
#ifndef HOVEREVENTFILTER_H
#define HOVEREVENTFILTER_H
#include <QObject>
#include <QEvent>
class HoverEventFilter : public QObject
{
Q_OBJECT
public:
explicit HoverEventFilter(QObject *parent = 0);
signals:
void HoverIn(QObject *);
void HoverOut(QObject *);
public slots:
protected:
bool eventFilter(QObject *watched, QEvent *event);
};
#endif // HOVEREVENTFILTER_H
hovereventfilter.cpp
#include "hovereventfilter.h"
HoverEventFilter::HoverEventFilter(QObject *parent) : QObject(parent)
{
}
bool HoverEventFilter::eventFilter(QObject *watched, QEvent *event)
{
QEvent::Type t = event->type();
switch(t){
case QEvent::Enter:
emit HoverIn(watched);
break;
case QEvent::Leave:
emit HoverOut(watched);
break;
default:
return false;
}
return true;
}
Puedes ver que esta clase disparará HoverIn o HoverOut dependiendo de lo que sucedió. Este enfoque no necesita la configuración de Qt::WA_Hover
Ahora como último paso, debemos indicar qué elementos se filtrarán y conectar señales y ranuras. Crearé un puntero privado al filtro de eventos en mainwindow.h
class MainWindow : public QWidget
{
Q_OBJECT
...
public slots:
void onHoverIn(QObject* object);
void onHoverOut(QObject* object);
private:
HoverEventFilter* hoverEventFilter;
...
};
Y en el constructor, agrego esto:
this->hoverEventFilter = new HoverEventFilter(this);
connect(this->hoverEventFilter, SIGNAL(HoverIn(QObject*)), this, SLOT(onHoverIn(QObject*)));
connect(this->hoverEventFilter, SIGNAL(HoverOut(QObject*)), this, SLOT(onHoverOut(QObject*)));
Ahora, cada vez que deseo recibir eventos flotantes en algún objeto, simplemente configuro el filtro de eventos, de esta forma:
this->ui->someLabelOrWhatever->installEventFilter(this->hoverEventFilter);
Lo que queda es la implementación de onHoverIn
y onHoverOut
en MainWindow
. Ambos comparten la misma idea, por lo que solo mostraré onHoverIn
void MainWindow::onHoverIn(QObject *object)
{
QString objectName = object->objectName();
switch(objectName){
// do something depending on name of the widget
}
}
Puede extender esto tan fácilmente, para procesar eventos flotantes en un nuevo elemento, simplemente configure un detector de eventos en él y cuide lo que desea hacer en el onHoverIn
y enHoverOut
métodos. No es necesario subclasificar ningún widget.
QHoverEvent
es solo para los widgets de desplazamiento, desea implementar los controladores enterEvent
y leaveEvent
subclasificando el widget en su lugar.
Si desea utilizar un filtro de eventos, los tipos de eventos correspondientes son QEvent :: Enter
y QEvent :: Leave
.
Si simplemente necesita cambiar la apariencia del widget, puede consultar las hojas de estilo Qt, ya que proporcionan un selector : hover
.
Debe subclasificar o filtrar focusInEvent y focusOutEvent de ese widget en particular.