我延长了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)
谁能告诉我有什么问题?
不幸的是,小部件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渲染?
我的要求是禁用鼠标点击.按照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)