Qt 之QWebEngineVie框架简介及加载网页方法

基于Widget的QWebEngine架构

通过本篇文章,大致可以了解基于Widget的QWebEngine框架的几个关键类。

QWebEngine结构图
由上图可见,从上至下,呈现一种树状结构。

QWebEngineView

A web view is the main widget component of the Qt WebEngine web browsing module. It can be used in various applications to display web content live from the Internet.

根据Qt官方的描述,QWebEngineView 具备了加载从Internet加载网页的基本能力。
官方Demo可以看出

QWebEngineView *view = new QWebEngineView(parent);
view->load(QUrl("http://qt-project.org/"));
view->show();

再看来具体类内部包含了哪些接口

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef QWEBENGINEVIEW_H
#define QWEBENGINEVIEW_H

#include <QtGui/qpainter.h>
#include <QtNetwork/qnetworkaccessmanager.h>
#include <QtWidgets/qwidget.h>

#include <QtWebEngineWidgets/qtwebenginewidgetsglobal.h>
#include <QtWebEngineWidgets/qwebenginepage.h>
#include <QtWebEngineCore/qwebenginehttprequest.h>

QT_BEGIN_NAMESPACE
class QContextMenuEvent;
class QUrl;
class QWebEnginePage;
class QWebEngineSettings;
class QWebEngineViewAccessible;
class QWebEngineViewPrivate;

class QWEBENGINEWIDGETS_EXPORT QWebEngineView : public QWidget {
    Q_OBJECT
    Q_PROPERTY(QString title READ title)
    Q_PROPERTY(QUrl url READ url WRITE setUrl)
    Q_PROPERTY(QUrl iconUrl READ iconUrl NOTIFY iconUrlChanged)
    Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged)
    Q_PROPERTY(QString selectedText READ selectedText)
    Q_PROPERTY(bool hasSelection READ hasSelection)
    Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor)

public:
    explicit QWebEngineView(QWidget* parent = Q_NULLPTR);
    virtual ~QWebEngineView();

    QWebEnginePage* page() const;            //QWebEnginePage
    void setPage(QWebEnginePage* page);

    void load(const QUrl &url);
    void load(const QWebEngineHttpRequest &request);
    void setHtml(const QString& html, const QUrl& baseUrl = QUrl());
    void setContent(const QByteArray& data, const QString& mimeType = QString(), const QUrl& baseUrl = QUrl());

    QWebEngineHistory* history() const;

    QString title() const;
    void setUrl(const QUrl &url);
    QUrl url() const;
    QUrl iconUrl() const;
    QIcon icon() const;

    bool hasSelection() const;
    QString selectedText() const;

#ifndef QT_NO_ACTION
    QAction* pageAction(QWebEnginePage::WebAction action) const;
#endif
    void triggerPageAction(QWebEnginePage::WebAction action, bool checked = false);

    qreal zoomFactor() const;
    void setZoomFactor(qreal factor);
    void findText(const QString &subString, QWebEnginePage::FindFlags options = QWebEnginePage::FindFlags(), const QWebEngineCallback<bool> &resultCallback = QWebEngineCallback<bool>());

    QSize sizeHint() const override;
    QWebEngineSettings *settings() const;

public Q_SLOTS:
    void stop();
    void back();
    void forward();
    void reload();

Q_SIGNALS:
    void loadStarted();
    void loadProgress(int progress);
    void loadFinished(bool);
    void titleChanged(const QString& title);
    void selectionChanged();
    void urlChanged(const QUrl&);
    void iconUrlChanged(const QUrl&);
    void iconChanged(const QIcon&);
    void renderProcessTerminated(QWebEnginePage::RenderProcessTerminationStatus terminationStatus,
                             int exitCode);

protected:
    virtual QWebEngineView *createWindow(QWebEnginePage::WebWindowType type);
#if QT_CONFIG(contextmenu)
    void contextMenuEvent(QContextMenuEvent*) override;
#endif // QT_CONFIG(contextmenu)
    bool event(QEvent*) override;
    void showEvent(QShowEvent *) override;
    void hideEvent(QHideEvent *) override;
    void closeEvent(QCloseEvent *) override;
#if QT_CONFIG(draganddrop)
    void dragEnterEvent(QDragEnterEvent *e) override;
    void dragLeaveEvent(QDragLeaveEvent *e) override;
    void dragMoveEvent(QDragMoveEvent *e) override;
    void dropEvent(QDropEvent *e) override;
#endif // QT_CONFIG(draganddrop)

private:
    Q_DISABLE_COPY(QWebEngineView)
    Q_DECLARE_PRIVATE(QWebEngineView)
    QScopedPointer<QWebEngineViewPrivate> d_ptr;

    friend class QWebEnginePage;
    friend class QWebEnginePagePrivate;
#if QT_CONFIG(accessibility)
    friend class QWebEngineViewAccessible;
#endif
};

QT_END_NAMESPACE

#endif // QWEBENGINEVIEW_H

通过上面的类的定义,可以发现,其中有个page()接口,关于page()接口的描述:

The page() function returns a pointer to a web page object. A QWebEngineView contains a QWebEnginePage, which in turn allows access to the QWebEngineHistory in the page’s context.

  • page() 函数返回一个指向网页对象的指针。 QWebEngineView 包含一个 QWebEnginePage,它反过来允许访问页面上下文中的 QWebEngineHistory。

关于QWebEngineView下QWebEnginePage的疑问

上面说,page()返回一个指向网页对象的指针。QWebEngineView包含一个QWebEnginePage。 能不能包含多个呢? 大家知道,我们的Chrome浏览器,打开多个网页时,是有多个标签页的,这里的“标签页”,是不是可以和这里的page对应上呢?

这让我注意到了另一个接口: setPage(QWebEnginePage page)*

void QWebEngineView::setPage(QWebEnginePage *page)

Makes page the new web page of the web view.
The parent QObject of the provided page remains the owner of the object. If the current page is a child of the web view, it will be deleted.

  • 所提供页面的父 QObject 仍然是对象的所有者。 如果当前页面是 web 视图的子页面,它将被删除。

看到这里,我有点迷惑的。意思是新设置一个页面后,当前页面会被删除? 那岂不是始终只有一个page,起不到多标签页的效果。

应该是我理解的不对。知道我看到了官方的Demo, 稍后再详细介绍。

QWebEnginePage

A web engine page holds the contents of an HTML document, the history of navigated links, and actions.

正如上述结构图描述的那样,QWebEnginePage包含HTML内容,导航历史连接,和一些Actions。
这些Actions如:前进(Forward),后退(Back),停止(Stop),重新加载(Reload)等操作。

  • 要特别注意QWebEnginePage和QWebProfile的关系

All pages belong to a web engine profile that contains shared settings, scripts, and cookies. Profiles can be used to isolate pages from each other. A typical use case is a dedicated profile for a private browsing mode, where no information is permanently saved.

所有的页面(page)都属于一个web engine的Profile, 该profile包含共享配置,脚本和cookies。配置文件可用于将页面(pages)隔离。一个典型的用例是用于隐私浏览模式的专用配置文件,其中不会永久保存任何信息。

page和profile关系的疑惑

All pages belong to a web engine profile. 前半句说所有的页面都属于一个profile。 难道这个profile是一个集合。应该不是的,我们在浏览器的设置里面会发现如下两个选项:

  • New Window
  • New Private Window

那么在一个Window下的page,应该是都遵循了特定的profile. 因此上面那段描述说的隔离,应该是针对不同window下的profile而言的。这一点也可以在官方的Simple Browser看到。

  • QWebEnginePage下的三个内容

QWebEngineHistory

Each web engine page contains a history of visited pages that can be accessed by QWebEnginePage::history().

盲猜也是类似与历史记录之类的东西。先不详细了解。

QWebEngineAction

QWebEngineProfile

A web engine profile contains settings, scripts, persistent cookie policy, and the list of visited links shared by all web engine pages that belong to the profile.

看看QWebEngineProfile包含了哪些内容

  • settings
  • scripts
  • cookie
QWebEngineSettings

QWebEngineSettings allows configuration of browser properties, such as font sizes and families, the location of a custom style sheet, and generic attributes, such as JavaScript support. Individual attributes are set using the setAttribute() function. The WebAttribute enum further describes each attribute.

看类型名大概也可以猜出个一二三,像是类似浏览器的设置

  • 允许设置浏览器的属性,如字体大小和类型,一些常见的属性,比如是否支持JavaScript。WebAttribute描述了很多相关的属性。
QWebEngineScript

QWebEngineScript enables the programmatic injection of so called user scripts in the JavaScript engine at different points, determined by injectionPoint(), during the loading of web contents.

QWebEngineScript 允许在加载 Web 内容期间在 JavaScript 引擎中的不同点(由 injectionPoint() 确定)以编程方式注入所谓的用户脚本

Cookie related

和Cookie相关的大概有这么几个接口,这里先记录下,暂时不做研究

QWebEngineCookieStore *QWebEngineProfile::cookieStore();
QWebEngineProfile::PersistentCookiesPolicy	persistentCookiesPolicy() const;
void	setPersistentCookiesPolicy(QWebEngineProfile::PersistentCookiesPolicy newPersistentCookiesPolicy);

QWebEnginePage加载网页

QWebEngineView 类下,还有一个QWebEnginePage的类。 虽然QWebEngineView也有一个loadUrl接口,但是,大部分时候,还是以QWebEnginePage来加载网页。因为QWebEnginePage中有关于可以运行javascript的接口,而且可以通过QWebEngineHistory提供网页的浏览历史及导航,和一些QAction操作网页。

两种形式的加载接口

在QWebEnginePage中,其实有两个接口

  • load()接口
void QWebEnginePage::load(const QUrl &url)
// Loads url into this page.
// Note: The view remains the same until enough data has arrived to display the new URL.
// See also setUrl(), setHtml(), and setContent().

直接加载url到该page, 只有当数据足够多时,才会显示新的URL内容。 该接口相对简单。

  • setHtml()接口
void QWebEnginePage::setHtml(const QString &html, const QUrl &baseUrl = QUrl())
// Sets the content of this page to html. baseUrl is optional and used to 
//resolve relative URLs in the document, such as referenced images or stylesheets.

该接口第一个参数可以理解成某个html文件的内容,比如空白文件:

#define BLANK_HTML  "<!DOCTYPE html><html><head></head><body></body></html>"

The html is loaded immediately, external objects are loaded asynchronously.

和load接口不一样的是,html内容是立即加载,外部资源是异步加载。换言之,不需要像load() 接口,等到足够多的数据加载后,才显示新的内容。

If a script in the html runs longer than the default script timeout (currently 10 seconds), for example due to being blocked by a modal JavaScript alert dialog, this method will return as soon as possible after the timeout and any subsequent html will be loaded asynchronously

如果在html文件中的脚本运行时间超过默认的脚本超时时间10s, 比如因为一个alert对话框而阻阻塞超时, 该方法会立即返回,并且将异步加载任何后续html。

加载网页过程中的三个信号

网页加载的过程分为三步:

  • 开始
  • 加载中
  • 结束
Q_SIGNALS:
    void loadStarted();             
    void loadProgress(int progress);
    void loadFinished(bool);

当希望得知加载一个网页的时长时,可以在loadStarted()和loadFinished()处分别打时间。其中loadProgress()信号是持续发射的,比如40%, 80%处都会发射该信号。

加载网页结束后的操作

有些操作可能明确需要在网页打开后再执行,那么就可以在接收到loadFinished( )信号后再执行后续操作。比如打开摄像头, 启动新的线程。 否则,可能未就绪就执行了某些意外的操作。时序上得以控制。

WebEngine热启动

在初始化时,如果未通过webEngine加载一个空白页,当第一次点击业务,加载其他页面时,会造成打开网页非常慢的问题。因此,在初始化时,通过加载一个空白页,缩短进入具体业务的时间。

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值