如何使用 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 委托处理=]
可以捕获类型 QOpenGLWidget
的 QWebEngineView
的新 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
我扩展了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 委托处理=]
可以捕获类型 QOpenGLWidget
的 QWebEngineView
的新 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