QWebEngineView是比较新的Qt(这里指6.7.2版本)开发库中自带的Web浏览插件,属于做Qt开发过程中,不可多得的利器。
一般使用
如果在程序中使用QWebEngineView,需要包含它的头文件,连接它的库文件。
它的开发库需要单独安装。
如果是Fedora系统的非开发环境,只需要安装运行所需的库即可。
命令如下:
dnf install qt6-qtwebengine
但如果是开发环境,就不仅要安装运行所需的库,还需要安装开发所需要的库了。
如下:
dnf install qt6-qtwebengine-devel
这个开发包,不仅包含了QWebEngine必要的库,还有相应的pkg-config脚本,以及CMake的脚本。
这样,方便我们在使用CMake构建的项目中直接使用。
比如,可以使用如下命令来给手头的项目增加QWebEngine的支持。
FIND_PACKAGE (Qt6 NAMES Qt6 COMPONENTS WebEngine REQUIRED)
CMAKE_INCLUDE_DIR(${Qt6WebEngine_INCLUDE_DIRS)
ADD_EXECUTE(helloworld helloworld.cc)
TARGET_LINK_LIBRARIES(helloworld Qt6::WebEngine)
之后,就可以在项目中使用WebView来加载网页,相应的方法load,有两种调用方法。
void QWebEngineView::load(const QUrl &url)
void QWebEngineView::load(const QWebEngineHttpRequest &request)
QWebEngineSettings
如果要对QWebEngine的设置进行一些更改,可以使用QWebEngineSettings。
使用QWebEngineView的settings()方法,就可以取得它的实例,之后进行定制。
这个类支持的方法不太多,主要这么几个:
QString defaultTextEncoding() const
QString fontFamily(QWebEngineSettings::FontFamily which) const
int fontSize(QWebEngineSettings::FontSize type) const
void resetAttribute(QWebEngineSettings::WebAttribute attribute)
void resetFontFamily(QWebEngineSettings::FontFamily which)
void resetFontSize(QWebEngineSettings::FontSize type)
void resetUnknownUrlSchemePolicy()
void setAttribute(QWebEngineSettings::WebAttribute attribute, bool on)
void setDefaultTextEncoding(const QString &encoding)
void setFontSize(QWebEngineSettings::FontSize type, int size)
void setUnknownUrlSchemePolicy(QWebEngineSettings::UnknownUrlSchemePolicy policy)
bool testAttribute(QWebEngineSettings::WebAttribute attribute) const
QWebEngineSettings::UnknownUrlSchemePolicy unknownUrlSchemePolicy() const
如使用如下代码:
auto settings = view->settings ();
settings->setDefaultTextEncoding ("UTF-8");
就可以指定资源加载时的默认编码。
自定义协议
就像webkit2gtk一样,使用QWebEngine开发,当然也是有自定义协议的需求的。
但是,QWebEngine自定义协议的实现,明显比webkit2gtk要麻烦一些,其中涉及到几个类QWebEngineUrlScheme、QWebEngineUrlSchemeHandler、QWebEngineProfile以及QWebEngineUrlRequestJob。
大体实现方式就是:
- 子类化一个QWebEngineUrlSchemeHandler。
- 在QApplication初始化之前,先使用QWebEngineUrlScheme注册自己要支持的自定义协议。
- 创建一个自定义的QWebEngineUrlSchemeHandler子类,然后把它安装到在QWebEnineView关联的Profile里去。
- 在QWebEngineView里去执行load。
QWebEngineUrlSchemeHandler
QWebEngineUrlSchemeHandler是整个自定义协议的实现的核心部分,整个自定义获取资源的过程,都在这个类的requestStarted方法里。
以下是一个简单的样例,代码复制自QWebEngineUrlSchemeHandler的文档:
{
public:
MySchemeHandler(QObject *parent = nullptr);
void requestStarted(QWebEngineUrlRequestJob *job)
{
const QByteArray method = job->requestMethod();
const QUrl url = job->requestUrl();
if (isValidUrl(url)) {
if (method == QByteArrayLiteral("GET")) {
job->reply(QByteArrayLiteral("text/html"), makeReply(url));
else // Unsupported method
job->fail(QWebEngineUrlRequestJob::RequestDenied);
} else {
// Invalid URL
job->fail(QWebEngineUrlRequestJob::UrlNotFound);
}
}
bool isValidUrl(const QUrl &url) const // ....
QIODevice *makeReply(const QUrl &url) // ....
};
其中,返回给浏览器的地方在job的reply那个方法。
通过官方文档,我们看到这个reply方法有两个参数:
void QWebEngineUrlRequestJob::reply(const QByteArray &contentType, QIODevice *device)
第一个比较容易理解,就是资源的mime类型(样例里写死了是text/html),我们可以灵活使用写成别的。
第二个是Qt里面的一种QIODevice指针。比较麻烦的是,这个指针需要我们根据它的生命周期释放,否则会有内存泄漏。
官方文档给的建议方法是,给job的销毁信号,连接一个槽,来自动释放这个QIODevice。
如:
connect(job, &QObject::destroyed, device, &QObject::deleteLater);
需要注意的是,如果我们的资源有更多需要释放,这个槽的实现就要更全面一些。
QWebEngineUrlScheme
在程序开始的时候,亦即QApplication创建之前,需要把我们向自定义的协议,注册到QWebEngineUrlScheme中去。
如我们要注册一个hello协议,实现如下:
QWebEngineUrlScheme scheme ("hello");
scheme.setSyntax (QWebEngineUrlScheme::Syntax::Path);
QWebEngineUrlScheme::registerScheme (scheme);
其中,QWebEngineUrlScheme::Syntax是一个枚举类型,有HostPortAndUserInformation、HostAndPort、Host与Path四种。需要我们根据自己定义的协议,来正确设置这个类型。
QWebEngineProfile
在最终可以使用QWebEngineView的load方法,达到我们的自定义协议的目的之前,还需要把一个QWebEngineUrlSchemeHandler的实例,安装到与我们的QWebEngineView关联的profile上。
比较简单的实现是,安装到默认的QWebEngineProfile上。
如:
auto hanlder = new MySchemeHandler();
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler (QByteArray ("hello"), handler);
但是如果我们需要更定制化一些,比如每一个不同的QWebEngineView都需要不同的Handler实现,或者不同的实例化参数,就需要如下的方式来安装到特定的profile了。
auto profile = new QWebEngineProfile ();
auto view = new QWebEngineView (profile);
auto hanlder = new MySchemeHandler();
QWebEngineProfile::defaultProfile()->installUrlSchemeHandler (QByteArray ("hello"), handler);