Como posso implementar QHoverEvent em Qt?
Pergunta
Estou aprendendo Qt com C ++. Tenho sinais e slots para interceptar eventos padrão como ButtonPushed()
, etc. implementado com sucesso No entanto, eu quero ter uma função chamada quando eu mouse sobre e mouse para fora de um QLabel
. Parece QHoverEvent vai fazer o que eu preciso, mas eu não consigo para encontrar qualquer tutoriais ou exemplos sobre como implementar isso. É feito da mesma maneira como sinais e slots ?. Eu tentei:
connect(ui.lbl_test, SIGNAL(QHoverEvent), this, SLOT(TestFunc(QEvent::Type type, const QPoint & pos, const QPoint & oldPos)));
.. mas a função não se chamou quando eu pairava sobre o rótulo.
Aqui está a função, listados no arquivo de cabeçalho como um slot pública:
void MyDialog::TestFunc(QEvent::Type type, const QPoint & pos, const QPoint & oldPos) {
QMessageBox::information(this, tr("Hey"), tr("Listen!"));
}
Alguém pode me ajudar a descobrir isso ou me aponte para um bom exemplo?
EDIT:
Depois de ler um post abaixo, eu encontrei nenhum membro setFlag()
para pedir meu widget rótulo, mas eu fiz tentativa:
ui.lbl_test->setMouseTracking(true);
connect(ui.lbl_test, SIGNAL(ui.lbl_test->mouseMoveEvent()), this, SLOT(TestFunc(QMouseEvent *event)));
E TestFunc()
actualizado em conformidade. Mas ainda nada acontece quando eu mouse sobre.
Depois de olhar eu não tenho certeza QLabel
mesmo herda a mouseMoveEvent () até mesmo de QWidget
. Se isso for verdade, há um widget que faz, ou uma lista de objetos que herdam lo em algum lugar ?. Tudo o que posso dizer a partir da documentação em seu site é quantas funções um objeto herdou ..
Solução
Usando sinais e slots para este fim não está indo para o trabalho.
mouseMoveEvent()
não é um sinal ou meta-modo e não pode ser ligada a uma ranhura.
Subclassificação a classe widget e substituindo mouseMoveEvent()
irá permitir que você obtenha rato-move-eventos, mas que é uma maneira muito pesado para alcançar este objetivo (e acrescenta mais uma classe para sua base de origem).
Em vez disso, considere a implementação de um método eventFilter()
em sua classe MyDialog
e instalá-lo no QLabel
. Com este método filtro de eventos, você pode interceptar todos os eventos de uma determinada ocorrência QObject
.
Aqui está a documentação sobre filtros de eventos.
http://doc.qt.io/qt-4.8 /eventsandfilters.html#event-filters
Além disso, através do olhar para o exemplo de código, eu recomendo que você tome um momento para investigar o que os SIGNAL()
e SLOT()
macros fazer. Você pode ver como eles são definidos no $QTDIR/src/corelib/kernel/qobjectdefs.h
Outras dicas
De acordo com o link do documento que você dá você está indo só para obter este QHoverEvent se o seu widget tem a bandeira Qt::WA_Hover
.
Depois de construir a chamada Widget:
widget->setAttribute(Qt::WA_Hover);
e ver se funciona.
Outra forma de alcançar o mesmo resultado é substituir mouseMoveEvent()
em seu widget
Observe que essa função também não será normalmente chamado a menos que você ligue para:
widget->setMouseTracking(true);
Esta é, basicamente, como QT implementa o evento em foco internamente.
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
Forças Qt para gerar eventos de pintura quando o mouse entra ou sai do ferramenta. Este recurso é normalmente usado na implementação personalizada estilos; veja o exemplo Styles para mais detalhes.
Essa sobrecarga
QStyle::polish()
é chamado uma vez em cada Widget tirada usando o estilo. Nós reimplementar-lo para definir o atributoQt::WA_Hover
emQPushButtons
eQComboBoxes
. Quando esse atributo é definido, Qt gera eventos de pintura quando o ponteiro do mouse entra ou sai do ferramenta. Isso torna possível para tornar botões e comboboxes diferente quando o ponteiro do mouse está sobre eles.
Como receber Enter e Leave eventos em um QWidget
-
Defina o atributo Widget para WA_Hover
// in your widget's constructor (probably) this->setAttribute(Qt::WA_HOVER, true);
-
Implementar
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); }
-
Feito
QHoverEvent em QWidget
http://qt-project.org/doc/qt -5 / qhoverevent.html # detalhes
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:
Simples Exemplo
Passe o botão e ver a mudança contagem. Olhe para a saída do aplicativo para obter mais informações.
https://gist.github.com/peteristhegreat/d6564cd0992351f98aa94f869be36f77
Espero que ajude.
Eu estava tendo o mesmo problema, eu vim para o seguinte projeto de solução:
Na minha widget principal, eu gostaria de processar pairar eventos de alguns objetos selecionados. Por esta razão, eu criei 2 slots no meu MainWindow
:
public slots:
void onHoverIn(QObject* object);
void onHoverOut(QObject* object);
Em seguida, eu criei uma classe de Filtro de Eventos como este:
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;
}
Você pode ver esta classe irá disparar quer HoverIn ou HoverOut dependendo do que aconteceu. Esta abordagem não precisa de configurações do Qt::WA_Hover
Agora, como último passo, precisamos instruir quais elementos devem ser filtrados e sinais de conexão e slots. Vou criar um ponteiro privada para filtro de eventos em mainwindow.h
class MainWindow : public QWidget
{
Q_OBJECT
...
public slots:
void onHoverIn(QObject* object);
void onHoverOut(QObject* object);
private:
HoverEventFilter* hoverEventFilter;
...
};
E no construtor, eu acrescentar o seguinte:
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*)));
Agora, sempre que eu quiser receber pairar eventos em algum objeto, eu apenas definir filtro de eventos sobre ele, como este:
this->ui->someLabelOrWhatever->installEventFilter(this->hoverEventFilter);
O que resta é a implementação de onHoverIn
e onHoverOut
em MainWindow
. Ambos compartilham a mesma idéia por isso vou mostrar apenas onHoverIn
void MainWindow::onHoverIn(QObject *object)
{
QString objectName = object->objectName();
switch(objectName){
// do something depending on name of the widget
}
}
Você pode estender isso tão facilmente, para processar pairar eventos novo item, você apenas definir um ouvinte de evento sobre ele e cuidar do que você deseja fazer nos métodos onHoverIn
e onHoverOut
. Não há necessidade de subclasse quaisquer widgets.
QHoverEvent
apenas para widgets em foco, você deseja implementar os manipuladores enterEvent
e leaveEvent
por subclasse o widget em seu lugar.
Se você quiser usar um filtro de eventos em vez disso, os tipos de eventos correspondentes são QEvent::Enter
e QEvent::Leave
.
Se você simplesmente precisa para mudar a aparência do widget, você pode querer olhar para as folhas de estilo do Qt, como eles fornecem um seletor :hover
.
Você precisa subclasse ou filtro focusInEvent e focusOutEvent desse widget específico.