【问题标题】:How to disable the delivery of mouse events to the widget but not its children in Qt?如何禁用鼠标事件传递到小部件而不是 Qt 中的子部件?
【发布时间】:2015-03-07 10:53:27
【问题描述】:

在过去的两天里,我一直在寻找一种将鼠标事件传递给小部件背后的小部件的方法,该小部件用作其子级的容器/父级。我知道有一种方法可以使小部件对鼠标事件透明,如下所示:

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

但这也会禁止将鼠标事件传递给它的孩子!我希望前端小部件的子级和前端小部件后面的小部件接收鼠标事件。

Qt::WA_TransparentForMouseEvents:启用时,此属性将禁用鼠标事件传递给小部件及其子项。 鼠标事件被传递给其他小部件,就像小部件及其 小部件层次结构中不存在子级;鼠标点击和 其他事件有效地“通过”它们。这个属性是 默认禁用。

如果您对如何使小部件对鼠标事件透明但不是子事件有任何想法,请分享!

【问题讨论】:

    标签: qt mouseevent parent-child transparent


    【解决方案1】:

    终于找到了解决办法:)

    QWidget::setMask (const QRegion & region)

    https://doc.qt.io/qt-5/qwidget.html#setMask-1

    http://qt-project.org/doc/qt-4.8/qwidget.html#setMask

    我在这里找到了解决方案:http://www.qtcentre.org/archive/index.php/t-3033.html

    QRegion reg(frameGeometry());
    reg -= QRegion(geometry());
    reg += childrenRegion();
    setMask(reg);
    

    现在前端小部件的子级和前端小部件后面的小部件根据需要响应鼠标事件!

    请记住,每当重新调整前部小部件的大小以重新计算蒙版的几何形状时,您都需要再次调用这些行!

    void someWidget::resizeEvent(QResizeEvent *e){
      QWidget::resizeEvent(e);
      QRegion reg(frameGeometry());
      reg-=QRegion(geometry()); 
      reg+=childrenRegion();
      setMask(reg);
    }
    

    【讨论】:

    • 嘿,这就是我要找的东西,但我在 PYTHON 中!我正试图将你的示例翻译成 pyqt4,有什么想法吗?
    【解决方案2】:

    OP 的解决方案很棒而且非常优雅。为了完整起见,另一种选择是在鼠标事件到达容器小部件时忽略它们。可以通过子分类或eventFilter 来完成。

    如果小部件动态隐藏/显示许多子小部件并且计算掩码变得困难,则此解决方案会很有帮助。

    注意:如果您想在后台小部件中跟踪鼠标移动事件,则必须setMouseTracking(true) 才能在未按下任何按钮时接收(然后忽略)QEvent::MouseMove。 em>

    子类化示例

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

    【讨论】:

    • 这仅在假定透明小部件后面的小部件是其父小部件时才起作用。如果设置了WA_TransparentForMouseEvents,该事件不会传播到同级。
    猜你喜欢
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 2012-03-25
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多