2015-06-01 2 views
3

Я продлил QWebEngineView.Как я могу рисовать события с помощью QtWebEngine?

#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

Я бы вырыть в источник - Я не ожидаю QWebEngine быть самой живописи с помощью обычного механизма 'paintEvent', как его рендеринга, он основан на QtQuick 2 (и, таким образом, OpenGL) ... – peppe

+1

'QWebEngineView' не переопределяет' paint'. Если не использовать OpenGl-наложение, то возможно, что вся интеграция растра выполняется непосредственно в 'event'. Попробуйте вместо этого подключить это и посмотреть, не появятся ли какие-либо события рисования. –

+0

@KubaOber Не могли бы вы объяснить, «подцепить эту» часть? –

ответ

6

К сожалению, виджет 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.

Сигнал delegatePaint всегда излучается при изменении веб-представления каким-либо сценарием или путем выделения некоторых элементов управления веб-сайтом из-за наведения мыши или по любой другой причине.

Обратите внимание, что это не то же самое, что и переопределение QWebEngineView::paintEvent. Таким образом можно получить уведомление только о том, что что-то изменилось.

Таким образом, можно реагировать на события, непосредственно в WebEngineView::eventFilter или для подключения к сигналу delegatePaint уведомить другие объекты о веб-просмотра перекраску, например, см QT QWebEngine render after scrolling?

+0

Это не работает в 5.9. Любые идеи, как сделать что-то подобное для 5.9? – Dalamber

+0

Я смог заставить его «работать» с 5.9.2, проверяя, является ли 'child_ev-> child() -> metaObject() -> className()' равно "QtWebEngineCore :: RenderWidgetHostViewQtDelegateWidget" '. –

1

Мой спрос отключив мыши. Следуйте за ответом Ореста, «w» всегда имеет значение NULL в Qt 5.9.3.

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

Поэтому я изменяю ответ, следуя за Орестом. Это более подходит для 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 
Смежные вопросы