2010-03-15 15 views
11

Esto me ha estado molestando por más de dos días, así que pensé que debería preguntar. Estoy usando Qt 4.5.3 (compilado con VC2008) en Win7.QGraphicsView y eventFilter

Tengo clases MyGraphicsView (hereda QGraphicsView) y MyFilter (hereda QObject).

cuando instalo el objeto myFilter como un filtro de eventos a MyGraphicsView, eventos del ratón se entregan a myFilter después de que se entregan a MyGraphicsView mientras que los eventos clave son entregados a myFilter antes de ser entregados al MyGraphicsView.

En el segundo caso, se instala el objeto myFilter como un filtro de eventos a MyGraphicsView-> ventana gráfica() (que es un QGLWidget standart), eventos del ratón se entregan a myFilter antes de se entregan a MyGraphicsView, mientras que Key los eventos se entregan a solo MyGraphicsView.

Se supone que los eventos se entregarán a los filtros de eventos antes de que se entreguen al objeto real, entonces, ¿por qué sucede esto? ¿Qué debo hacer para garantizar esta orden?

Gracias de antemano. Atentamente.

+1

Dado que el ordet parece ser el problema, puede ser que un fragmento de su código sea útil. – gregseth

+0

OK Chicos, aquí está el enlace al código mínimo que reproduce el problema. http://rapidshare.com/files/363574158/QGVEF.rar – erelender

Respuesta

12

QGraphicsView es una subclase de QAbstractScrollArea que es la causa de estos comportamientos.

En el primer caso, QAbstractScrollArea se agrega como un filtro de eventos a MyGraphicsView cuando se llama a setViewport(). El filtro de eventos de QAbstractScrollArea captura el evento del mouse, primero lo envía a través de viewportEvent() y luego al manejo de eventos de QWidget que se propaga a los manejadores de eventos del mouse MyGraphicsView. Solo después de esto se termina el filtro de eventos de QAbstractScrollArea y se ejecuta MyFilter.

En el segundo caso, los eventos clave se entregan solo a MyGraphicsView porque en setViewport() el QAbstractScrollArea se establece a sí mismo como el proxy de enfoque. Si el proxy de enfoque se restablece con el siguiente código, se entregarán los eventos clave.

w.viewport()->setFocusProxy(0); 

Una alternativa es instalar el filtro de eventos tanto en la vista gráfica y su ventana, pero modificar el filtro para eventos clave única de proceso de eventos de un objeto y de ratón de la otra.

Cambio MyFilter.h

QObject *keyObj; 
    QObject *mouseObj; 

public: 
    MyFilter(QObject *keyObj, QObject *mouseObj, QObject *parent = NULL); 

Cambio MyFilter.cpp

MyFilter::MyFilter(QObject *keyObj, QObject *mouseObj, QObject *parent /*= NULL*/) : QObject(parent), keyObj(keyObj), mouseObj(mouseObj) 

y

if (obj == keyObj && e->type() == QEvent::KeyPress) 
{ 
    qDebug()<<"Key Event recieved by MyFilter"; 
} 
else if (obj == mouseObj && e->type() == QEvent::MouseButtonPress) 
{ 
    qDebug()<<"Mouse Event recieved by MyFilter"; 
} 

Cambio main.cpp

MyFilter *filter = new MyFilter(&w, w.viewport(), &w); 

// Use this line to install to the viewport 
w.viewport()->installEventFilter(filter); 

//Use this line to install to MyGraphicsView 
w.installEventFilter(filter); 
+0

En realidad, esto es lo que estoy haciendo en este momento, pero creo que es más como una solución, no como una solución. Mis filtros de eventos provienen de complementos y no creo que manejar el filtrado de eventos basado en objetos sea su preocupación. Sin embargo, gracias por la explicación de por qué esto está sucediendo. – erelender

+0

Aunque creo que mi explicación anterior fue en general correcta, creo que esta es ahora una mejor explicación. Si no le importa el manejo de eventos de tecla del área de desplazamiento (página arriba, página abajo, etc.), instalar el filtro de eventos en la ventana gráfica y borrar su proxy de enfoque es una solución más simple. De lo contrario, la instalación del filtro de eventos tanto en MyGraphicsView como en la ventana gráfica es probablemente mejor. – baysmith

+0

Tiene razón, su solución anterior podría ser más adecuada para uso general. En mi caso, estoy tratando de hacer algunas cosas elegantes con Qt & OSG, que es la razón por la cual la mayoría de mis problemas quedan sin resolver :). Esta solución se ajusta a mi caso como un guante, gracias. Pero, para referencia futura, ¿puede publicar su solución anterior como otra respuesta para que otros puedan verla? Se puede acceder a través del enlace "edited: ... ago". – erelender

-2

¿Qué hay que tratar de no usar filtro, pero reimplementar manipuladores QEvent necesarias en MyGraphicsView como aquí:

void MyGraphicsView::mousePressEvent(QMouseEvent* pe) 
{ 
if (pe->buttons() & Qt::LeftButton) 
{ 
    this->setCursor(Qt::CrossCursor); 
    zoomOrigin = pe->pos(); 
    rubberBand = new QRubberBand(QRubberBand::Rectangle, this); 
    rubberBand->setGeometry(QRect(zoomOrigin, QSize(0,0))); 
    rubberBand->show(); 
} 
if (pe->buttons() & Qt::MidButton) 
{ 
    panOrigin = pe->pos(); 
     this->setCursor(Qt::ClosedHandCursor); 
} 
} 
+0

Ya lo hago. Pero la subclasificación y el filtrado de eventos son para diferentes propósitos y no intercambiables en mi caso. – erelender

+1

OK, si realmente necesita el filtrado de eventos puede haber un problema con el valor verdadero/falso devuelto por el método eventFilter(), asegúrese de que no sea un caso para usted. También cargo proyecto de prueba a http://uploading.com/files/7c7adam5/graphicsview.zip/ que maneja eventos como se supone. Ha sido compilado en Slackware Linux con la versión actual de Git de Qt. Entonces, si este proyecto de prueba no funciona con su versión de Qt (4.5.3) puede ser un problema con Qt que ya está solucionado, pero no me parece un caso. También puede ser una "característica" dependiente de la plataforma. ¡Buena suerte! –

+0

Su ejemplo también funciona bien con Qt 4.5.3 porque no es el mismo caso que el mío. En su ejemplo, las subclases de GraphicsView QWidget, no QGraphicsView. También el filtro de eventos está instalado en graphicsview (subclase de QWidget), no en QGraphicsView, publiqué el código de muestra que reproduce el problema. Si lo miras, comprenderás mejor mi problema. – erelender

Cuestiones relacionadas