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 ...

¿Fue útil?

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.

http: / /qt-project.org/doc/qt-5/qtwidgets-widgets-styles-example.html#norwegianwoodstyle-class-implementation

  

Esta sobrecarga de QStyle :: polish () se llama una vez en cada widget dibujado   usando el estilo. Lo reimplementamos para establecer el atributo Qt :: WA_Hover   en QPushButtons y QComboBoxes . 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

  1. Establezca el atributo del widget para WA_Hover

    // in your widget's constructor (probably)
    this->setAttribute(Qt::WA_HOVER, true);
    
  2. Implemente QWidget :: enterEvent () y QWidget :: 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);
    }
    
  3. 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.

https://gist.github.com/peteristhegreat/d6564cd0992351 compcccgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggam

Espero que ayude.

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 .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top