Как реализовать QHoverEvent в Qt?
Вопрос
Я только изучаю 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 генерировать события краски, когда мышь входит или покидает виджет.Эта функция обычно используется при реализации пользовательских стилей;подробности см. в примере «Стили».
Этот
QStyle::polish()
Перегрузка вызывается один раз на каждом виджете, нарисованном с помощью стиля.Мы переопределяем его, чтобы установитьQt::WA_Hover
атрибут наQPushButtons
иQComboBoxes
.Когда этот атрибут установлен, QT генерирует события краски, когда указатель мыши входит или покидает виджет.Это позволяет по -разному отображать кнопки нажатия и комбо, когда указатель мыши над ними.
Как получать события входа и выхода на QWidget
Установите атрибут виджета для WA_Hover
// in your widget's constructor (probably) this->setAttribute(Qt::WA_HOVER, true);
Осуществлять
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); }
Сделанный
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 этого конкретного виджета.