文章目录
一、注意点
- QtWebkits在Qt5.6以上版本被淘汰了,不可用,需要使用QWebEngine;
- 安装Qt的时候需要勾选QWebEngine,这样才可以使用该模块;
- QWebEngine目前不支持MinGW编译器(
Project ERROR: Unknown module(s) in QT: webenginewidgets),只支持MSVC编译器;
二、QWebEngineView、QWebEnginePage、QWebChannel详解
QWebEngine架构如下图所示:

2.1、QWebEngineView
①、作用
web视图【QWebEngineView】是Qt WebEngine web浏览模块的主要小部件组件,它可以在各种应用程序中用于实时显示来自Internet的web内容。
可以使用load()函数将网站加载到web视图中。GET方法总是用于加载url。
像所有Qt小部件一样,必须调用show()函数才能显示web视图。下面的代码片段说明了这一点:
QWebEngineView *view = new QWebEngineView(parent);
view->load(QUrl (" http://qt-project.org/ "));
view->show();
load()直接加载url到该page, 只有当数据足够多时,才会显示新的URL内容。 该接口相对简单。
或者,setUrl()可以用来加载一个网站。如果有现成的HTML内容,则可以使用setHtml()。
setHtml(const QString &html, const QUrl &baseUrl = QUrl())
该接口第一个参数可以理解成某个html文件的内容,比如空白文件:
#define BLANK_HTML "<!DOCTYPE html><html><head></head><body></body></html>"
和load接口不一样的是,html内容是立即加载,外部资源是异步加载。换言之,不需要像load() 接口,等到足够多的数据加载后,才显示新的内容。
如果在html文件中的脚本运行时间超过默认的脚本超时时间10s, 比如因为一个alert对话框而阻阻塞超时, 该方法会立即返回,并且将异步加载任何后续html。
WebEngine热启动
在初始化时,如果未通过webEngine加载一个空白页,当第一次点击业务,加载其他页面时,会造成打开网页非常慢的问题。因此,在初始化时,通过加载一个空白页,缩短进入具体业务的时间。
②、信号
loadStarted()信号在视图开始加载时发出;loadProgress()信号在web视图的一个元素完成加载时发出,比如一个嵌入的图像或一个脚本;loadFinished()信号在视图被完全加载时发出。它的参数为true或false,指示加载是成功还是失败。
③、成员函数
page()函数的作用是: 返回一个指向网页对象的指针。一个QWebEngineView包含一个QWebEnginePage,它允许在页面的上下文中访问QWebEngineHistory。- HTML文档的标题可以通过
title()属性访问; - 网站可以指定一个图标,可以使用
icon()或使用iconUrl()属性访问图标的URL; - 如果标题或图标发生变化,则会发出相应的
titleChanged()、iconChanged()和iconUrlChanged()信号; zoomFactor()属性允许按比例因子缩放网页内容。
这个小部件具有一个上下文菜单,该菜单是为手头的元素量身定制的,并包括在浏览器中有用的操作。对于自定义上下文菜单,或者在菜单或工具栏中嵌入操作,可以通过pageAction()获取单个操作。web视图维护返回操作的状态,但允许修改操作属性,如文本或图标。动作语义也可以通过triggerPageAction()直接触发。
如果你想为允许用户打开新窗口(如弹出窗口)的网站提供支持,你可以子类化QWebEngineView并重新实现createWindow()函数。
2.2、QWebEnginePage
QWebEngineView 类下,还有一个QWebEnginePage的类。 虽然QWebEngineView也有一个loadUrl接口,但是,大部分时候,还是以QWebEnginePage来加载网页。因为QWebEnginePage中有关于可以运行javascript的接口,而且可以通过QWebEngineHistory提供网页的浏览历史及导航,和一些QAction操作网页。
2.3、QWebChannel
QWebChannel填补了c++应用程序和HTML/JavaScript应用程序之间的空白,通过将QObject派生对象发布到QWebChannel,并在HTML端使用QWebChannel .js,可以透明地访问QObject的属性、公共槽和方法。不需要手动消息传递和数据序列化,c++端的属性更新和信号发射会自动传输到可能远程运行的HTML客户端。在客户端,将为任何已发布的c++ QObject创建JavaScript对象。它反映了c++对象的API,因此直观上是可用的。
c++ QWebChannel API可以与任何HTML客户端对话,这些客户端可以运行在本地甚至远程机器上。唯一的限制是HTML客户端支持qwebchannel.js使用的JavaScript特性。因此,基本上可以与任何现代HTML浏览器或独立的JavaScript运行时(如node.js)进行交互。
三、使用说明
1、在.pro文件中添加模块
QT += webenginewidgets
QT += network
2、添加头文件
#include <QtWebEngineWidgets/QWebEngineView>

3、访问在线网页
ui->widget->setUrl(QUrl("https://www.bilibili.com/"));
//此处的widget已提升为了QWebEngineView

4、访问本地本地网页
ui->widget->setUrl(QUrl("E:/workspace/Qt_workspace/Qt_JS_Demo/test.html"));
ui->widget->setZoomFactor(0.5); //设置缩放比例
四、网页无法响应鼠标键盘
通过上面的使用说明,打开网页已经基本没有问题了,但是测试发现,当对网页使用鼠标点击标签时,网页并没有跳转。
此时需要继承QWebEngineView,重新实现createWindow()函数,即可解决这个问题;
#ifndef QWEBENGINEVIEWCHW_H
#define QWEBENGINEVIEWCHW_H
#include <QWidget>
#include <QWebEngineView>
#include <qwebenginepage.h>
#include <qurl.h>
#include <QMouseEvent>
#include <QApplication>
class QWebEngineViewChw : public QWebEngineView
{
Q_OBJECT
public:
explicit QWebEngineViewChw(QWidget *parent = nullptr);
~QWebEngineViewChw()override;
protected:
QWebEngineView* createWindow(QWebEnginePage::WebWindowType type) override;
private slots:
void slot_LinkHovered(const QString& url);
private:
QUrl url_;
QVector<QObject *> mvchildObj;
protected:
bool event(QEvent* evt)override;
bool eventFilter(QObject *obj, QEvent *ev)override;
};
#endif // QWEBENGINEVIEWCHW_H
#include "qwbengineviewchw.h"
QWebEngineViewChw::QWebEngineViewChw(QWidget *parent) : QWebEngineView(parent)
{
setAttribute(Qt::WA_DeleteOnClose);
connect(this->page(), &QWebEnginePage::linkHovered, this, &QWebEngineViewChw::slot_LinkHovered);
}
QWebEngineViewChw::~QWebEngineViewChw()
{
}
QWebEngineView *QWebEngineViewChw::createWindow(QWebEnginePage::WebWindowType type)
{
//加载链接地址
if(!url_.isEmpty())
{
this->load(url_);
emit QEvent::ChildPolished;//重新加载页面时,手动触发一个ChildPolished事件
}
// return this;
return nullptr;
}
void QWebEngineViewChw::slot_LinkHovered(const QString &url)
{
//获取视图里面点击的链接地址
// qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<url;
url_.setUrl(url);
}
bool QWebEngineViewChw::event(QEvent *evt)
{
//每次新加载URL时手动触发该事件,生成一个QChildEvent
if (evt->type() == QEvent::ChildPolished)
{
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" ";
QChildEvent *child_ev = static_cast<QChildEvent*>(evt);
QObject *childObj = child_ev->child();
mvchildObj.append(childObj);
if (childObj)
{
childObj->installEventFilter(this);
}
}
return QWebEngineView::event(evt);
}
bool QWebEngineViewChw::eventFilter(QObject *obj, QEvent *ev)
{
foreach(QObject *childObj,mvchildObj)
{
if (obj == childObj)
{
if (/*obj == childObj&& */(ev->type() == QEvent::MouseButtonPress|| ev->type() == QEvent::MouseButtonDblClick))
{
QMouseEvent *MouseEvent = static_cast<QMouseEvent *>(ev);
int x = MouseEvent->x();
int y = MouseEvent->y();
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<x <<y;
return QWebEngineView::eventFilter(obj, ev);
}
}
}
return QWebEngineView::eventFilter(obj, ev);
}
1046

被折叠的 条评论
为什么被折叠?



