Как передать событие 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;
}
Надеюсь, что это поможет.