Как передать событие click для sibling под Qt?

У меня есть два совпадающих виджета в дочернем окне окна A и потомке B. Ребенок A находится выше B и получает события мыши, но иногда клик должен пройти и, в конечном счете, нажать дочерний элемент B.

Идеальное решение заключалось бы в использовании event->ignore(), но это передает событие родительскому виджету, а не братьям и сестрам.

Решение "передать все" setAttribute(Qt::WA_TransparentForMouseEvents); не работает либо потому, что дочерний элемент A должен захватывать некоторые события.

Как сказать Qt "Я не хочу обрабатывать это событие, действуйте так, как будто меня там нет"?

Ответ 1

Если событие должно быть проигнорировано Child-A, испустите сигнал и запишите его со своим родителем, тогда родитель испускает новый сигнал, который будет захвачен Child-B

Ребенок-A → Родитель → Ребенок-B
(Сигнал) → (Слот) (Сигнал) → (Слот)

Ответ 2

Более простым решением (если применимо) является установка WA_TransparentForMouseEvents в зависимости от вашего условия перехода по клику.

Например, если вы хотите щелкнуть по некоторым регионам Child-A, вы можете использовать его mouseMoveEvent(), чтобы проверить, нужно ли установить или отключить WA_TransparentForMouseEvents. Затем нажмите события автоматически.

Если вы не можете определить, должно ли событие клика быть принято до его фактического запуска, вы можете сделать что-то вроде этого:

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);
}

Отказ от ответственности: все это записано наизусть после года, когда вы не делали Qt, поэтому, пожалуйста, исправьте меня по ошибке имени или типа.

Ответ 3

Вы также можете обратиться к проблеме с другой стороны. Вместо того, чтобы пересылать события в "другой" виджет, вы можете подключить другой виджет к событиям для первого виджета, используя фильтр событий. Я не уверен, что это соответствует вашему варианту использования, это зависит от того, что/кто определяет, какие события должны обрабатываться каким-либо объектом.

Ответ 4

Вот возможная опция:

  • дать ребенку указатель B дочернему объекту. objet.
  • redefine bool QObjet:: event (событие QEvent *), чтобы при необходимости обновить событие до ребенка B.

Например:

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;

 }

Надеюсь, что это поможет.