如何使用 QtWebEngine 获取绘画事件?

How can I get paint events with QtWebEngine?

我扩展了QWebEngineView

#ifndef MYQWEBENGINEVIEW_H
#define MYQWEBENGINEVIEW_H
#include <QWebEngineView>
class MyQWebEngineView : public QWebEngineView
{
public:
    MyQWebEngineView(QWidget *parent = 0);
    ~MyQWebEngineView();
protected:
    virtual void paintEvent(QPaintEvent *);
};
#endif // MYQWEBENGINEVIEW_H

但是我无法接到 paintEvent(QPaintEvent *) 电话。

#include "myqwebengineview.h"
#include <QPaintEvent>
#include <QPainter>
#include <QWebEngineView>
#include <QWidget>

MyQWebEngineView::MyQWebEngineView(QWidget *parent):QWebEngineView(parent)
{
    qDebug() << "MyQWebEngineView(" << parent << ")";
    qDebug() << "Qt::WA_PaintOnScreen: " << testAttribute(Qt::WA_PaintOnScreen);
    //setAttribute(Qt::WA_PaintOnScreen, true);
}
MyQWebEngineView::~MyQWebEngineView()
{
}
void MyQWebEngineView::paintEvent(QPaintEvent * event)
{
    qDebug() << "paintEvent(" << event << ")";
    QWebEngineView::paintEvent(event);
    //QWidget::paintEvent(event);

    qDebug() << event->rect();
    qDebug() << event->region();
}

谁能告诉我怎么了?

不幸的是,小部件 QWebEngineView 几乎没有捕获任何事件(除了鼠标进入和退出,最近添加的键盘事件),例如参见 [​​=27=]。

几乎所有事件(如鼠标移动或绘画)都由派生自 QOpenGLWidget.[=29 的私有类型 RenderWidgetHostViewQtDelegateWidget QWebEngineView child 委托处理=]

可以捕获类型 QOpenGLWidgetQWebEngineView 的新 child 并在此 child 上安装所有需要的事件的事件过滤器挂钩。

该解决方案依赖于 QWebEngineView 的未记录结构。因此,未来的 Qt 版本可能不支持它。但是,它可用于具有当前 Qt 版本的项目。也许将来会实现一些更方便的接口来捕获 QWebEngineView 事件。

QWebEngineView 的以下子类实现了:

#ifndef WEBENGINEVIEW_H
#define WEBENGINEVIEW_H

#include <QEvent>
#include <QChildEvent>
#include <QPointer>
#include <QOpenGLWidget>
#include <QWebEngineView>
#include <QPaintEvent>

class WebEngineView : public QWebEngineView
{
    Q_OBJECT

private:
    QPointer<QOpenGLWidget> child_;

protected:
    bool eventFilter(QObject *obj, QEvent *ev)
    {
        // emit delegatePaint on paint event of the last added QOpenGLWidget child
        if (obj == child_ && ev->type() == QEvent::Paint) {
            QPaintEvent *pe = static_cast<QPaintEvent*>(ev);
            // do something with paint event
            // ...
            // or just emit signal to notify other objects
            emit delegatePaint(pe);
        }

        return QWebEngineView::eventFilter(obj, ev);
    }

public:
    WebEngineView(QWidget *parent = nullptr) :
        QWebEngineView(parent), child_(nullptr)
    {
    }

    bool event(QEvent * ev)
    {
        if (ev->type() == QEvent::ChildAdded) {
            QChildEvent *child_ev = static_cast<QChildEvent*>(ev);

            // there is also QObject child that should be ignored here;
            // use only QOpenGLWidget child
            QOpenGLWidget *w = qobject_cast<QOpenGLWidget*>(child_ev->child());
            if (w) {
                child_ = w;
                w->installEventFilter(this);
            }
        }

        return QWebEngineView::event(ev);
    }

signals:
    void delegatePaint(QPaintEvent*);
};

#endif // WEBENGINEVIEW_H

Child 添加被WebEngineView::event捕获。 child 指针被保存,事件过滤器被安装在这个 child 上。在 child 绘画事件中,信号 WebEngineView::delegatePaint(QPaintEvent*)WebEngineView::eventFilter.

中发出

当 Web 视图被某些脚本更改或由于鼠标悬停或任何其他原因突出显示某些 Web 控件时,总是会发出信号 delegatePaint

请注意,它与覆盖 QWebEngineView::paintEvent 不同。这样就可能只接收到某些内容发生更改的通知。

因此,可以直接在 WebEngineView::eventFilter 中对事件做出反应,或者连接到信号 delegatePaint 以通知其他 objects Web 视图重绘,例如参见

我的需求是禁用鼠标点击。 按照 Orest 的回答,Qt 5.9.3 中的 "w" 始终为 NULL。

QOpenGLWidget *w = qobject_cast<QOpenGLWidget*>(child_ev->child());

所以我按照Orest修改答案。那更适合Qt 5.9.x.

#ifndef CUSTOMWEBVIEW_H
#define CUSTOMWEBVIEW_H

#include <QWebEngineView>
#include <QOpenGLWidget>
#include <QDebug>
#include <QEvent>

class CustomWebView : public QWebEngineView
{
    Q_OBJECT

public:
    CustomWebView(QWidget* parent = Q_NULLPTR);

protected:
    bool event(QEvent* evt)
    {
        qDebug() << evt->type();

        if (evt->type() == QEvent::ChildPolished)
        {
            QChildEvent *child_ev = static_cast<QChildEvent*>(evt);
            childObj = child_ev->child();

            if (childObj)
            {
                childObj->installEventFilter(this);
            }
        }

        return QWebEngineView::event(evt);
    }

    bool eventFilter(QObject *obj, QEvent *ev)
    {
        if (obj == childObj
                && (ev->type() == QEvent::MouseButtonPress
                    || ev->type() == QEvent::MouseButtonDblClick))
        {
            return true;
        }

        return QWebEngineView::eventFilter(obj, ev);
    }

private:
    QObject *childObj = NULL;
};

#endif // CUSTOMWEBVIEW_H