从webkit到webengine
自从Qt5.6后引入了QWebEngine,摒弃了原先的QWebkit,这是一款基于chrome浏览器内核引擎,Qt webenginewidgets模块中提供了QWebEngineView这个视图控件来很方便的加载和显示网页,仅需如下几行:
QWebEngineView* webview = new QWebEngineView;
webview->load(QUrl("/"));
webview->show();
QWebEngineView跳转问题
这段代码很容易运行起来,但是别高兴早了,接下来你会发现点页面上的链接或者百度到其它页面时无法跳转,这是为什么呢?
因为我们只是一个浏览器引擎,不是像firefox、chrome那样的浏览器,浏览器已经提供了tab页去显示一个新的链接,所以这里我们需要自己决定如何去显示新打开的链接。
有两种方法可以实现
1、我们发现点击链接时时会收到urlChanged信号的,它附带的参数就是url地址,所以如果你想在本webview视图上显示这个页面就直接在绑定的槽函数里调用load(url)就ok了,如果你想实现向浏览器用另一tab来显示也是可以的,只需另外创建一个QWebEngineView,加载显示就好了,当然你也可以跳出一个对话框来显示,就想新打开一个浏览器窗口一样;
2、第二种方法就是重写createWindow方法,默认返回的是NULL,所以我们看到的效果是无法显示新的链接,因为你没有提供一个QWebEngineView给它嘛,在这个方法里有一个WebWindowType类型参数,
enum WebWindowType {
WebBrowserWindow,
WebBrowserTab,
WebDialog
};
可以看到就是第一种方法中我们提到的三种显示,本浏览器窗口视图显示,另一tab页显示,跳出新的对话框显示,分别给你想实现的效果就好啦,简单而灵活。实际上js里面的就会触发这个动作,调用到这个方法。
示例代码:
class HWebView : public QWebEngineView
{
Q_OBJECT
public:
HWebView::HWebView(QWidget *parent)
: QWebEngineView(parent){
}
protected:
virtual QWebEngineView *createWindow(QWebEnginePage::WebWindowType type){
HWebView* view = new HWebView;
view->setAttribute(Qt::WA_DeleteOnClose);
view->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
return view;
}
};
c++和JS交互
因为Qt自带的元对象模型Meta Object Model,信号与槽机制,使得c++和JS的交互异常简单而优雅,可以说比微软的com组件更加好用。
这里隆重登场的就是QWebChannel了,它使用了QWebSocket了,在C++端开了一个服务器端口,在JS客户端去连接这个端口,然后利用qt的元对象模式,信号与槽机制进行交换,说的很复杂,实际请看代码,很简单
class HWebContext : public QObject{
Q_OBJECT
signals:
void sigClicked();
public slots:
void setAction(int action);
};
QWebChannel* webchannel = new QWebChannel(m_webview);
m_webview->page()->setWebChannel(webchannel);
m_webContext = new HWebContext;
webchannel->registerObject(QStringLiteral("content"), (QObject*)m_webContext);
首先我们定义一个c++和JS进行交互的对象类,这个类需要继承自QObject,加上Q_OBJECT宏,定义一些信号和槽,这样就可以使用qt的信号与槽机制了.
然后new一个QWebChannel,与QWebEngineView里面的QWebEnginePage绑定起来,用registerObject去注册我们定义的c++和JS进行交互的对象。
这样c++端的工作就完成了,c++端实际上开了一个端口去监听,提供了一个对象供js去使用。
在JS端需要做的工作如下:
<script type="text/javascript" src="./"></script>
var g_context;
function onClicked(){
}
=function(){
new QWebChannel(, function(channel) {
g_context= ;
g_context.(onClicked())
});
}
g_context.setAction(0);
加载,这个文件在qt安装目录下搜索可以找到,然后在窗口加载时利用QWebChannel,实际上是链接到了c++服务器端,获取到我们在c++端注册的对象,content是c++端注册时为对象设置的字符串标识,为这个对象的信号连接一个槽函数(js函数),这样c++端发出信号时就会去调用这个js函数,而js端调用c++槽函数更加简单,直接类似g_context.setAction(0)就可以了。
清理缓存、浏览记录、cookie
QWebEngineView view;
()->profile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
()->profile()->clearHttpCache(); // 清理缓存
()->profile()->clearAllVisitedLinks(); // 清理浏览记录
QWebEngineCookieStore* pCookie = ()->profile()->cookieStore();
pCookie->deleteAllCookies(); // 清理cookie
pCookie->deleteSessionCookies(); // 清理会话cookie
部署
使用了webenginewidgets模块的,除了需要所需的库lib目录外,还有一些目录也需要一并拷贝过来,分别是libexec qml resources translations
此外需要在程序运行目录下写上配置文件
[Paths]
Prefix=.