Как отключить доставку событий мыши виджету, но не его дочерним элементам в Qt?

С последних двух дней я ищу и выясняю способ передачи событий мыши виджетам позади виджета, используемого в качестве контейнера/родителя для его детей. Я знаю, что есть способ сделать виджет прозрачным для событий мыши, как это:

QWidget w;
w.setAttribute( Qt::WA_TransparentForMouseEvents );

но это также отключает доставку событий мыши своим детям! На самом деле я хочу, чтобы дети переднего виджета и виджеты за передним виджетом реагировали на события мыши.

Qt:: WA_TransparentForMouseEvents: при включении этот атрибут отключает доставку событий мыши виджету и его дочерним элементам. События мыши доставляются в другие виджеты, как если бы виджет и его дети не присутствовали в иерархии виджетов; щелчки мыши и другие события эффективно "проходят" через них. Этот атрибут по умолчанию отключено.

Если у вас есть идеи о том, как сделать виджет прозрачным для событий мыши, но не для детей тогда, пожалуйста, поделитесь!

2 ответов


наконец-то я нашел решение :) Этот ответ для тех, кто находится в поисках решения для такого рода проблем.


решение OP является удивительным и очень элегантным. Просто для полноты другой вариант-игнорировать события мыши, когда они достигают виджета контейнера. Это можно сделать либо путем подкласса, либо через eventFilter.

это решение может быть полезно, если виджет скрывает / показывает много дочерних виджетов динамически и вычисление маски становится трудным.

Примечание: В случае, если вы хотите отслеживать мышь-перемещение событий в фоновых виджетах, тебе придется ... --13-->setMouseTracking(true) чтобы получить (а затем игнорировать)QEvent::MouseMove когда кнопка не нажата.

пример по подклассу

ContainerWidget::ContainerWidget(...) {
  setMouseTracking(true);
}

void ContainerWidget::mouseMoveEvent(QMouseEvent* e) {
  e->ignore();
}
void ContainerWidget::mousePressEvent(QMouseEvent* e) {
  e->ignore();
}

пример использования фильтра событий

// Assume the container widget is configured in the constructor
MainWindow::MainWindow(...) {
  // ...
  containerWidget->installEventFilter(this);
  containerWidget->setMouseTracking(true);
  // ...
}

bool MainWindow::eventFilter(QObject* o, QEvent* e) {
  if (o == containerWidget &&
     (e->type() == QEvent::MouseMove || e->type() == QEvent::MouseButtonPress)) {
    e->ignore();
    return false;
  }
  return QMainWindow::eventFilter(o, e);
}