2011-04-06 13 views
10

Tengo dos widgets superpuestos en una ventana hijo A e hijo B. El hijo A está por encima de B y obtiene eventos de mouse pero a veces el clic debe pasar y finalmente golpear niño B.¿Cómo pasar evento de clic a hermano debajo en Qt?

La solución ideal habría sido usar event->ignore() pero esto pasa el evento al widget principal, no a los hermanos.

La solución "pasar todo" setAttribute(Qt::WA_TransparentForMouseEvents); tampoco funciona porque el elemento secundario A necesita capturar algunos eventos.

¿Cómo le digo a Qt "No quiero manejar este evento, actuar como si no estuviera allí"?

+0

¿Puede establecer la opción "pasar todo" y volver a enviar el evento del mouse desde el controlador de eventos del mouse? Después de que el evento se haya completado, configúralo como falso nuevamente. Podría causar una recursión infinita. Tal vez debería instalar un filtro de eventos en la ventana principal para el niño A, intente si A gestiona el evento; si no, verifique si está en el área del niño B y, de ser así, páselo a eso. Esto debería funcionar, pero podría ser un poco complicado. De lo contrario, vería la posibilidad de que A sepa B y sea capaz de pasarle eventos. – 0xbaadf00d

+0

Al buscar el código fuente de Qt, 'QWidgetPrivate :: childAtRecursiveHelper' encuentra un elemento secundario correspondiente (filtrando aquellos con' WA_TransparentForMouseEvents' y luego llama al controlador de eventos del niño pero esta llamada ocurre fuera del método de búsqueda de niños por lo que la única solución parece administrar el clic Oportunidades a mano del padre ... – gaspard

Respuesta

1

Si el evento tiene que ser ignorado por Child-A, emiten una señal y capturarlo con su padre, entonces el padre emite una nueva señal para ser capturado por Child-B

Niño-A -> Padres -> Child-B
(señal) -> (ranura) (señal) -> (Slot)

1

La solución más fácil (si es aplicable) es establecer WA_TransparentForMouseEvents dependiendo de su condición de clics.

Por ejemplo, si desea hacer clic a través de ciertas regiones de Child-A, puede usar su mouseMoveEvent() para verificar si WA_TransparentForMouseEvents necesita establecerse o no. A continuación, haga clic en eventos que pasan automáticamente.

Si no puede determinar si un evento de clic debe ser aceptado antes de que realmente se ha activado, se puede hacer algo como esto:

void ChildA::mousePressEvent(QMouseEvent* event) { 
    const bool accepted = ...; //insert custom logic here 
    if (accepted) { 
     ... //handle event here 
    } else { 
     //not accepting event -> resend a copy of this event... 
     QMouseEvent* eventCopy = new QMouseEvent(*event); 
     QApplication::instance()->postEvent(eventCopy); 
     //...but this time, ignore it 
     setAttribute(Qt::WA_TransparentForMouseEvents, true); 
     QTimer::singleSlot(1, this, SLOT(resetClickTransparency())); 
     //don't propagate original event any further 
     event->accept(); 
    } 
} 

void ChildA::resetClickTransparency() { //slot 
    setAttribute(Qt::WA_TransparentForMouseEvents, false); 
} 

responsabilidad: Todo esto anotado por el corazón después de un año de no hacer Qt, por favor corrígeme por nombre o tipo de errores.

+0

Sé que esto es viejo, pero para que lo sepas, no puedo configurarlo en falso una vez que lo activé. – Romain

0

Aquí es una opción posible:

  1. dar el puntero infantil B para el niño Un objet.
  2. redefinir bool QObjet :: event (evento QEvent *) para revertir el evento al niño B siempre que sea necesario.

Por ejemplo:

bool WidgetA::event(QEvent *event) 
{ 
    QWidget::event(event); 
    QEvent::Type type = event->type(); 
    if ((type != QEvent::KeyPress) && 
     (type != QEvent::Wheel) && 
     (type != QEvent::MouseButtonDblClick) && 
     (type != QEvent::MouseMove) && 
     (type != QEvent::MouseButtonPress)) 
     return true; 
    //forward the event 
    if (m_pChildB) 
     m_pChildB->event(event); 
    return true; 

} 

Espero que esto ayude.

1

También puede abordar el problema desde el otro lado. En lugar de reenviar eventos al widget "otro", puede hacer que su otro widget escuche eventos para el primer widget utilizando un filtro de eventos. No estoy seguro si eso se ajusta a su caso de uso, depende de qué/quién determina qué eventos deben ser manejados por qué objeto.

Cuestiones relacionadas