Как мне реализовать QHoverEvent в Qt? - PullRequest
7 голосов
/ 05 января 2009

Я только изучаю Qt с C ++. Я успешно реализовал сигналы и слоты для перехвата стандартных событий, таких как ButtonPushed() и т. Д. Тем не менее, я хочу, чтобы функция вызывалась при наведении курсора мыши на 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)));

И обновил TestFunc() соответственно. Но все равно ничего не происходит, когда я нахожу курсор мыши.

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

Ответы [ 6 ]

13 голосов
/ 05 января 2009

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

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

widget->setAttribute(Qt::WA_Hover);

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

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

widget->setMouseTracking(true);

Это в основном то, как QT реализует событие hover внутри.

8 голосов
/ 16 октября 2014

http://qt -project.org / док / кварта-5 / qwidget.html # enterEvent

http://qt -project.org / док / кварта-5 / qwidget.html # leaveEvent

http://qt -project.org / док / кварты-5 / qt.html # виджет-атрибуты

Qt :: WA_Hover

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

http://qt -project.org / док / кварта-5 / qtwidgets-виджеты-стили-example.html # norwegianwoodstyle-класс-реализация

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

Как получать события входа и выхода на 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 / док / кварты-5 / qhoverevent.html # подробности

http://qt -project.org / док / кварта-5 / qobject.html # событие

http://qt -project.org / док / кварта-5 / qwidget.html # событие

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

UPDATE:

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

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

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

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

7 голосов
/ 06 января 2009

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

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

Создание подкласса класса виджета и переопределение mouseMoveEvent() позволит вам получать события перемещения мышью, но это очень тяжелый способ для этого (и добавляет еще один класс в базу вашего источника).

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

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

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

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

2 голосов
/ 26 октября 2016

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

В моем основном виджете я хотел бы обрабатывать события наведения некоторых выбранных объектов. По этой причине я создал 2 слота на моем 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. Нет необходимости создавать подклассы для каких-либо виджетов.

1 голос
/ 30 июля 2013

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

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

0 голосов
/ 08 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...