Как реализовать 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 генерировать события рисования, когда мышь входит или выходит из штучка. Эта функция обычно используется при реализации пользовательских стили; см. стили пример для деталей.
этой
QStyle::polish()перегрузка вызывается один раз на каждый виджет рисуется используя стиль. Мы переопределяем его, чтобы установить onQPushButtonsиQComboBoxes. Когда этот атрибут установлен, Qt генерирует события paint, когда указатель мыши входит или выходит из штучка. Это позволяет визуализация кнопок и комбинаций иначе, когда указатель мыши находится над ними.
как получить Enter и оставить события на 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
надеюсь, это поможет.
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 этого конкретного виджета.