Come posso implementare QHoverEvent in Qt?
Domanda
Sto solo imparando Qt con C ++. Ho implementato con successo segnali e slot per intercettare eventi standard come ButtonPushed ()
, ecc. Tuttavia, voglio avere una funzione chiamata quando passo il mouse e mi sposto da un QLabel
. Sembra che QHoverEvent farà ciò di cui ho bisogno, ma non riesco a sembrare per trovare tutorial o esempi su come implementarlo. È fatto allo stesso modo di segnali e slot ?. Ho provato:
connect(ui.lbl_test, SIGNAL(QHoverEvent), this, SLOT(TestFunc(QEvent::Type type, const QPoint & pos, const QPoint & oldPos)));
.. ma la funzione non è stata chiamata quando ho passato il mouse sopra l'etichetta.
Ecco la funzione, elencata nel file di intestazione come uno slot pubblico:
void MyDialog::TestFunc(QEvent::Type type, const QPoint & pos, const QPoint & oldPos) {
QMessageBox::information(this, tr("Hey"), tr("Listen!"));
}
Qualcuno può aiutarmi a capirlo o indicarmi un buon esempio?
EDIT:
Dopo aver letto un post di seguito, non ho trovato alcun membro setFlag ()
da chiamare per il mio widget etichetta, ma ho provato:
ui.lbl_test->setMouseTracking(true);
connect(ui.lbl_test, SIGNAL(ui.lbl_test->mouseMoveEvent()), this, SLOT(TestFunc(QMouseEvent *event)));
E aggiornato TestFunc ()
di conseguenza. Ma non succede nulla quando passo il mouse sopra.
Dopo aver guardato non sono sicuro che QLabel
erediti anche mouseMoveEvent () anche da QWidget
. Se questo è vero, esiste un widget o un elenco di oggetti che lo ereditano da qualche parte ?. Tutto ciò che posso dire dalla documentazione sul loro sito è quante funzioni ereditate ha un oggetto ..
Soluzione
L'uso di segnali e slot a questo scopo non funzionerà.
mouseMoveEvent ()
non è un segnale o un meta-metodo e non può essere collegato a uno slot.
La sottoclasse della classe del widget e l'override di mouseMoveEvent ()
ti consentiranno di ottenere eventi di spostamento del mouse, ma questo è un modo molto pesante per raggiungere questo obiettivo (e aggiunge un'altra classe alla tua base di origine ).
Invece, considera di implementare un metodo eventFilter ()
sulla tua classe MyDialog
e installalo su QLabel
. Con questo metodo di filtro eventi, puoi intercettare tutti gli eventi per una determinata istanza QObject
.
Ecco la documentazione sui filtri degli eventi.
http://doc.qt.io/qt-4.8 /eventsandfilters.html#event-filters
Inoltre, guardando l'esempio di codice, ti consiglio di dedicare un momento a indagare su cosa fanno le macro SIGNAL ()
e SLOT ()
. Puoi vedere come sono definiti in $QTDIR/src/corelib/kernel/qobjectdefs.h
Altri suggerimenti
In base al link del documento fornito, otterrai questo QHoverEvent solo se il tuo widget ha il flag Qt :: WA_Hover
.
Dopo aver creato la chiamata al widget:
widget->setAttribute(Qt::WA_Hover);
e vedi se funziona.
Un altro modo per ottenere lo stesso risultato è sostituire mouseMoveEvent ()
nel tuo widget
si noti che anche questa funzione non verrà normalmente chiamata a meno che non si chiami:
widget->setMouseTracking(true);
Questo è fondamentalmente il modo in cui QT implementa internamente l'evento hover.
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
Forza Qt a generare eventi di disegno quando il mouse entra o esce da widget di. Questa funzione viene in genere utilizzata durante l'implementazione personalizzata stili; vedere l'esempio degli stili per i dettagli.
Questo sovraccarico
QStyle :: polish ()
viene chiamato una volta su ogni widget disegnato usando lo stile. Lo reimplementiamo per impostare l'attributoQt :: WA_Hover
suQPushButtons
eQComboBoxes
. Quando questo attributo è impostato, Qt genera eventi di disegno quando il puntatore del mouse entra o esce da widget di. Ciò rende possibile il rendering di pulsanti e combobox diversamente quando il puntatore del mouse è su di essi.
Come ricevere Enter and Leave Events su un QWidget
-
Imposta l'attributo del widget per WA_Hover
// in your widget's constructor (probably) this->setAttribute(Qt::WA_HOVER, true);
-
Implementa
QWidget :: enterEvent ()
eQWidget :: 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); }
-
Fatto
QHoverEvent in QWidget
http://qt-project.org/doc/qt -5 / qhoverevent.html # details
http://qt-project.org/doc/qt -5 / qobject.html # evento
http://qt-project.org/doc/qt -5 / qwidget.html # evento
// 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:
Esempio semplice
Passa con il mouse sul pulsante e guarda il conteggio cambiare. Guarda l'output dell'applicazione per ulteriori informazioni.
https://gist.github.com/peteristhegreat/d6564cd099235f8a77f
Spero che sia d'aiuto.
Avevo lo stesso problema, sono arrivato al seguente progetto di soluzione:
Nel mio widget principale, vorrei elaborare gli eventi al passaggio del mouse di alcuni oggetti selezionati. Per questo motivo, ho creato 2 slot sul mio MainWindow
:
public slots:
void onHoverIn(QObject* object);
void onHoverOut(QObject* object);
Quindi ho creato una classe Filtro eventi come questa:
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;
}
Puoi vedere che questa classe genererà HoverIn o HoverOut a seconda di ciò che è successo. Questo approccio non richiede impostazioni di Qt::WA_Hover
Ora, come ultimo passo, dobbiamo indicare quali elementi devono essere filtrati e collegare segnali e slot. Creerò un puntatore privato al filtro eventi in mainwindow.h
class MainWindow : public QWidget
{
Q_OBJECT
...
public slots:
void onHoverIn(QObject* object);
void onHoverOut(QObject* object);
private:
HoverEventFilter* hoverEventFilter;
...
};
E nel costruttore, aggiungo questo:
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*)));
Ora ogni volta che desidero ricevere eventi hover su un oggetto, ho appena impostato il filtro eventi su di esso, in questo modo:
this->ui->someLabelOrWhatever->installEventFilter(this->hoverEventFilter);
Ciò che rimane è l'implementazione di onHoverIn
e onHoverOut
in MainWindow
. Entrambi condividono la stessa idea, quindi mostrerò solo onHoverIn
void MainWindow::onHoverIn(QObject *object)
{
QString objectName = object->objectName();
switch(objectName){
// do something depending on name of the widget
}
}
Puoi estenderlo così facilmente, per elaborare gli eventi al passaggio del mouse su un nuovo elemento, devi solo impostare un listener di eventi su di esso e prenderti cura di ciò che desideri fare in onHoverIn
e onHoverOut
. Non è necessario sottoclassare alcun widget.
QHoverEvent
è solo per i widget hover, si desidera implementare i gestori enterEvent
e leaveEvent
subclassando invece il widget.
Se invece si desidera utilizzare un filtro eventi, i tipi di evento corrispondenti sono QEvent :: Enter
e QEvent :: Leave
.
Se hai semplicemente bisogno di cambiare l'aspetto del widget, potresti voler esaminare i fogli di stile Qt, in quanto forniscono un selettore : hover
.
Devi sottoclassare o filtrare focusInEvent e focusOutEvent di quel particolare widget.