Ver Mensaje Individual
  #3 (permalink)  
Antiguo 09/12/2015, 02:42
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 5 meses
Puntos: 204
Respuesta: Qt. ¿Como propagar eventos de escena del raton a items?

Dado que el objeto Cruceta no es un QWidget no tiene "presencia" en el formulario, luego no puede recibir eventos directamente. Digamos que lo que sucede es que tu "pintas" el objeto de forma explícita, de tal forma que el contenedor no sabe que en esas coordenadas hay un objeto al que deba pasarle eventos.

Tienes varias soluciones:

Usar señales

Puedes crear una señal en el objeto escena que exponga el evento que te interesa, en este caso mouseMove. Entonces simplemente haces un connect para cada objeto que deba conocer ese evento y listo:

Código C++:
Ver original
  1. class Cruceta
  2.   : public QObject // necesario para los eventos.
  3.                    // Se puede sustituir por cualquier objeto que herede de QObject
  4. {
  5.   Q_OBJECT // necesario para los eventos
  6.  
  7.     public slot:
  8.       void MouseMove(QGraphicsSceneMouseEvent *event)
  9.       { }
  10. };
  11.  
  12. class Scene // Por qué cruceta en español y scene en inglés???
  13. {
  14.   signals:
  15.     // Recuerda que las señales no tienen implementación, de eso se encarga qt.
  16.     void OnMouseMove(QGraphicsSceneMouseEvent *event);
  17. };
  18.  
  19. void Scene::Scene(...)
  20. {
  21.   // O como se llame tu objeto, tampoco es necesario que se cree aquí
  22.   cruceta = new Cruceta(...);
  23.  
  24.   // Eso sí, esto hay que hacerlo después de crear tu objeto cruceta
  25.   connect(this, SIGNAL(OnMouseMove(QGraphicsSceneMouseEvent*)),
  26.           cruceta, SLOT(MouseMove(QGraphicsSceneMouseEvent*)));
  27. }
  28.  
  29. void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
  30. {
  31.     emit OnMouseMove(event); // Emitimos la señal
  32.  
  33.     // ------------------
  34.     // (Aqui sigue actuando el evento)
  35. }

Usar el patrón observer

Esta solución es similar a la anterior pero basada en C++ puro.

Necesitas una clase base para los suscriptores de los eventos. Lo ideal es que sea una clase virtual pura para reducir acoplamientos:

Código C++:
Ver original
  1. class Subscriber
  2. {
  3.   public:
  4.     void MouseMove(QGraphicsSceneMouseEvent* event) = 0;
  5. };

El siguiente paso es hacer que tu objeto Cruceta herede de esta nueva clase. Como Subscriber es virtual pura no te debería ocasionar muchos problemas si tienes que recurrir a la herencia múltiple:

Código C++:
Ver original
  1. class Cruceta
  2.  : public Subscriber, /* Tus propias herencias */
  3. {
  4.   public:
  5.     void MouseMove(QGraphicsSceneMouseEvent* event ) override
  6.     { }
  7. };

Y para terminar metemos mano al objeto Scene. Una forma de resolver esta papeleta consiste en tener una lista de suscriptores, así se puede propagar el evento con un simple bucle:

Código C++:
Ver original
  1. class Scene
  2. {
  3.   std::vector<Subscriber*> _subscribers;
  4.  
  5.   public:
  6.     Scene()
  7.     {
  8.        _cruceta = new Cruceta;
  9.        
  10.        Attach(_cruceta);
  11.     }
  12.  
  13.     void Attach(Subscriber* newSubscriber)
  14.     { _subscribers.push_back(newSubscriber); }
  15.  
  16.     void MouseMove(QGraphicsSceneMouseEvent* event)
  17.     {
  18.       // la segunda línea es una lambda, no te asustes :)
  19.       std::for_each(_subscribers.begin(),_subscribers.end(),
  20.                     [event](Subscriber* ptr) { ptr->MouseMove(event); });
  21.     }
  22. };

Cualquiera de estos dos mecanismos te permite separar ambas capas de código. La única diferencia es que la primera solución aprovecha las capacidades de Qt mientras que en la segunda lo tienes que cocinar todo a mano :)

Un saludo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.