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

Jin*_*won 4 qt 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
Run Code Online (Sandbox Code Playgroud)

但我不能被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();
}
Run Code Online (Sandbox Code Playgroud)

谁能告诉我有什么问题?

Ore*_*era 7

不幸的是,小部件QWebEngineView几乎不会捕获任何事件(除了鼠标进入和退出,最近添加的键盘事件),例如,参见"[QTBUG-43602] WebEngineView不处理鼠标事件".

几乎所有事件(如鼠标移动或绘制)都由派生自QWebEngineView的私有类型的子委托处理.RenderWidgetHostViewQtDelegateWidgetQOpenGLWidget

可以捕获QWebEngineView类型的新子节点QOpenGLWidget并在此子节点上安装所有需要事件的事件过滤器挂钩.

该解决方案依赖于未记录的结构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
Run Code Online (Sandbox Code Playgroud)

添加儿童被抓住了WebEngineView::event.保存子指针并在此子项上安装事件过滤器.在儿童油漆事件中,信号WebEngineView::delegatePaint(QPaintEvent*)被发射出去WebEngineView::eventFilter.

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

请注意,它与覆盖不同QWebEngineView::paintEvent.通过这种方式,只能接收有关更改内容的通知.

因此,可以直接对事件做出反应WebEngineView::eventFilter或连接到信号delegatePaint以通知其他对象有关Web视图重新绘制的内容,例如在滚动后查看QT QWebEngine渲染?


Pul*_*ler 5

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

QOpenGLWidget *w = qobject_cast<QOpenGLWidget*>(child_ev->child());
Run Code Online (Sandbox Code Playgroud)

所以我按照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
Run Code Online (Sandbox Code Playgroud)