Как реализовать QHoverEvent в Qt?

Я просто изучаю Qt с C++. Я успешно реализовал сигналы и слоты для ловушки стандартных событий, таких как ButtonPushed(), etc. Тем не менее, я хочу, чтобы функция вызывалась при наведении мыши и мыши из QLabel. Похоже на QHoverEvent будет делать то, что мне нужно, но я не могу найти никаких учебников или примеров о том, как это реализовать. Это делается так же, как сигналы и слоты?. Я попробовал:

connect(ui.lbl_test, SIGNAL(QHoverEvent), this, SLOT(TestFunc(QEvent::Type type, const QPoint & pos, const QPoint & oldPos)));

.. но функция не была вызвана, когда я навис над этикеткой.

вот функция, перечисленная в заголовочном файле как открытый слот:

void MyDialog::TestFunc(QEvent::Type type, const QPoint & pos, const QPoint & oldPos) {
     QMessageBox::information(this, tr("Hey"), tr("Listen!"));
}

может кто-нибудь помочь мне или мне точку хороший пример?

EDIT:

прочитав сообщение ниже, я не нашел setFlag() член, чтобы вызвать мой виджет метки, но я попытался:

    ui.lbl_test->setMouseTracking(true);
    connect(ui.lbl_test, SIGNAL(ui.lbl_test->mouseMoveEvent()), this, SLOT(TestFunc(QMouseEvent *event)));

и обновляется!--6--> соответственно. Но все равно ничего не происходит при наведении мышки.

после просмотра я не уверен QLabel даже наследует mouseMoveEvent () даже от QWidget. Если это правда, есть виджет, который делает или список объектов, которые наследуют его где-нибудь?. Все, что я могу сказать из документации на их сайте, - это сколько унаследованных функций имеет объект..

6 ответов


использование сигналов и слотов для этой цели не будет работать.

mouseMoveEvent() не является сигналом или мета-методом и не может быть подключен к слоту.

подклассы класса виджетов и переопределение mouseMoveEvent() позволит вам получить mouse-move-events, но это очень тяжелый способ выполнить это (и добавляет еще один класс к вашей исходной базе).

вместо этого рассмотрите возможность реализации eventFilter() метод MyDialog класс и установка его на QLabel. С помощью этого метода фильтра событий вы можете перехватить все события для данного QObject экземпляра.

вот документация по фильтрам событий.

http://doc.qt.io/qt-4.8/eventsandfilters.html#event-filters

кроме того, посмотрев на образец кода, я бы рекомендовал вам воспользоваться моментом, чтобы исследовать, что SIGNAL() и SLOT() макросы делать. Вы можете увидеть, как они определены в $QTDIR/src/corelib/kernel/qobjectdefs.h


согласно ссылке документа, которую вы даете, вы только собираетесь получить этот QHoverEvent, если ваш виджет имеет Qt::WA_Hover флаг.

после построения вызова виджета:

widget->setAttribute(Qt::WA_Hover);

и посмотреть, если это работает.

другой способ достижения того же результата-переопределить mouseMoveEvent() в виджете
обратите внимание, что эта функция также не будет обычно вызываться, если вы не вызовете:

widget->setMouseTracking(true);

это в основном то, как QT реализует событие наведения внутренне.


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

заставляет Qt генерировать события рисования, когда мышь входит или выходит из штучка. Эта функция обычно используется при реализации пользовательских стили; см. стили пример для деталей.

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

этой QStyle::polish() перегрузка вызывается один раз на каждый виджет рисуется используя стиль. Мы переопределяем его, чтобы установить on QPushButtons и QComboBoxes. Когда этот атрибут установлен, Qt генерирует события paint, когда указатель мыши входит или выходит из штучка. Это позволяет визуализация кнопок и комбинаций иначе, когда указатель мыши находится над ними.

как получить Enter и оставить события на QWidget

  1. установите атрибут виджета для WA_Hover

    // in your widget's constructor (probably)
    this->setAttribute(Qt::WA_HOVER, true);
    
  2. реализовать QWidget::enterEvent() и 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. сделал

QHoverEvent в От QWidget

http://qt-project.org/doc/qt-5/qhoverevent.html#details

http://qt-project.org/doc/qt-5/qobject.html#event

http://qt-project.org/doc/qt-5/qwidget.html#event

// 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);
}

обновление:

Простой Пример:

наведите курсор на кнопку и увидите изменение количества. Посмотрите на вывод приложения для более информация.

https://gist.github.com/peteristhegreat/d6564cd0992351f98aa94f869be36f77

надеюсь, это поможет.


QHoverEvent только для виджетов наведения, вы хотите реализовать enterEvent и leaveEvent обработчики вместо подклассы виджетов. Если вы хотите использовать фильтр событий, соответствующих типов событий QEvent::Enter и QEvent::Leave.

Если вам просто нужно изменить внешний вид виджета, вы можете посмотреть таблицы стилей Qt, поскольку они предоставляют :hover селектор.


у меня была такая же проблема, я пришел к следующему дизайну решения:

в моем главном виджете я хотел бы обработать события наведения некоторых выбранных объектов. По этой причине я создал 2 слота на my MainWindow:

public slots:
    void onHoverIn(QObject* object);
    void onHoverOut(QObject* object);

затем я создал класс фильтра событий следующим образом:

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;
}

вы можете видеть, что этот класс будет срабатывать либо HoverIn, либо HoverOut в зависимости от что случилось. этот подход не требует настройки Qt::WA_Hover

теперь, как последний шаг, нам нужно указать, какие элементы должны быть отфильтрованы и соединить сигналы и слоты. Я создам частный указатель на фильтр событий в mainwindow.h

class MainWindow : public QWidget
{
    Q_OBJECT

...

public slots:
    void onHoverIn(QObject* object);
    void onHoverOut(QObject* object);

private:

    HoverEventFilter* hoverEventFilter;

...

};

и в конструкторе я добавляю это:

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*)));

теперь, когда я хочу получить события наведения на какой-либо объект, я просто устанавливаю фильтр событий на нем, например:

this->ui->someLabelOrWhatever->installEventFilter(this->hoverEventFilter);

что слева-реализация onHoverIn и onHoverOut на MainWindow. Они оба разделяют ту же идею, так что я покажу просто onHoverIn

void MainWindow::onHoverIn(QObject *object)
{
    QString objectName = object->objectName();

    switch(objectName){
        // do something depending on name of the widget
    }
}

вы можете расширить это так легко, чтобы обрабатывать события наведения на новый элемент, вы просто установите прослушиватель событий на нем и позаботьтесь о том, что вы хотите сделать в onHoverIn и onHoverOut методы. Нет необходимости подкласса каких-либо виджетов.


вам нужно подкласс или фильтр focusInEvent и focusOutEvent этого конкретного виджета.