Как реализовать 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 этого конкретного виджета.