Вопрос

Я только изучаю 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!"));
}

Может ли кто-нибудь помочь мне разобраться в этом или указать на хороший пример?

РЕДАКТИРОВАТЬ:

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

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

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

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

Это было полезно?

Решение

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

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

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

Вместо этого рассмотрите возможность внедрения eventFilter() метод на вашем MyDialog class и установив его на 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() Перегрузка вызывается один раз на каждом виджете, нарисованном с помощью стиля.Мы переопределяем его, чтобы установить 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/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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top