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

时间:2015-06-01 05:23:56

标签: 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

但是我无法调用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();
}

有人可以告诉我出了什么问题吗?

2 个答案:

答案 0 :(得分:7)

不幸的是,小部件QWebEngineView几乎不会捕获任何事件(鼠标进入和退出,最近添加的键盘事件除外),例如,请参阅"[QTBUG-43602] WebEngineView does not handle mouse events"

几乎所有事件(如鼠标移动或绘制)都由QWebEngineView私有类型RenderWidgetHostViewQtDelegateWidget的子代理处理,该代理来自QOpenGLWidget

可以捕获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

WebEngineView::event抓住了儿童添加内容。保存子指针并在此子项上安装事件过滤器。在子绘画事件中,信号WebEngineView::delegatePaint(QPaintEvent*)将在WebEngineView::eventFilter中发出。

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

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

因此,可以直接在WebEngineView::eventFilter中对事件做出反应,或者连接到信号delegatePaint以通知其他对象有关Web视图重新绘制的信息,例如,请参阅QT QWebEngine render after scrolling?

答案 1 :(得分:5)

我的要求是禁用鼠标点击。 按照Orest的回答,&#34; w&#34;在Qt 5.9.3中始终为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