QtWebkits如何向QtWebEngine過渡

1. 前言

很遺憾,QtWebkits在Qt5.6以上版本被淘汰了,對於這個接口良且和其餘類例如QWebFrame完美結合的組件就這麼沒了,我只能表示可惜。對於QtWebEngine新的組件,不得不認可它從Chromium繼承過來的強大的性能,但接口上還不是很豐富,和其餘類的交互也不是很完美,期待Qt可以對其進行進一步開發,我也會不斷的升級Qt,嘗試新的接口。javascript

目前而言,QWebEngine有如下缺點:html

  • MinGW版本的Qt不支持,即使是Qt5.6版本以上也是不支持的。僅僅支持MSVC版本。
  • 接口暫時不豐富
  • 沒法和QWebFrame進行交互(使用了新的QWebChannel和QWebEnginePage組合進行交互)

基於咱們的GPS定位項目,參考:[Qt開發北斗定位系統融合百度地圖API及Qt程序打包發佈] ,咱們在該項目中使用的是Qt5.5版本,在嵌入的瀏覽器做爲加載地圖用的是QWebKits組件,咱們將其升級使用QWebEngine進行加載地圖,和HTML和JS進行交互。咱們以此爲例,進行簡要的介紹。java

2. 二者的UI上面的區別

你剛剛升級到Qt5.6版本可能在UI設計界面時候在組件中找不到QWebEngineView這個組件,沒法從這裏拖拽這個組件到你的UI界面上。我查閱了不少資料,看到別人常用 ui->webEngineview->... 這樣,我甚至懷疑是否由於安裝了其餘版本的Qt影響到了我,我卸載了包含5.6版本的全部Qt,又從新安裝了一遍,可是再重啓軟件後,依然沒有發現QWebEngineView這個鬼東西。在Qt5.5中你也能發現有這樣的組件QWebView,如圖1所示:c++

Qt舊版本中的WebKits項

QWebView組件能夠經過QWebFrame來進行HTML和JS的通訊,若是過渡到QWebEngineView,要是沒有這個UI組件的話,我如何把瀏覽器嵌入到軟件界面,實現網頁和軟件的混合編程呢。根據官方提供的一個例子中,cookiebrowser中找到了答案,這也是官方給的例子中,惟一一個嵌入到網頁中的!(不得不說,Qt給的例子很模糊不好!) 通過研究, QWebEngineView使用widget組件,拖拉出來是一個透明的組件,對着組件按右鍵->promote to.. ->選擇QWebEngineView,如圖2,完成操做。程序員

把Widget promote to 成QWebEngineView組件

有了QWebEngineView這個UI組件,咱們能夠在程序中調用其成員、方法和函數完成操做了。web

3. 使用方法區別

在使用方法上有很大的區別,能夠說是兩個徹底不一樣理念的東西,這裏爲了更通俗易懂,就不粘貼API文檔中函數解釋,就用最經常使用的!編程

#include <QtWebEngineWidgets>    // 基本組件
#include <QWebEnginePage>        // HTML頁面
#include <QWebChannel>          // C++和JS/HTML雙向通訊,代替了已淘汰的QtWebFrame的功能

在咱們的項目中一開始就要引入這樣的組件,但在咱們的項目中,沒有頻繁用到與JS的互相交互,因此這裏暫時沒有關於QWebChannel的使用方法,只留下這個接口。瀏覽器

如下爲區別:cookie


  • 在WebKits中的初始化:
QUrl url(strMapPath);        // strMapPath爲QString類,是你html文件的路徑
ui->webView->load(url);
ui->webView->setContentsMargins(0,0,0,0);
ui->webView->setTextSizeMultiplier(1);//設置網頁字體大小
connect(ui->webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
            this, SLOT(slotPopulateJavaScriptWindowObject()));

咱們會使用load方法加載html所在的界面,使用QWebFrame類的mainFrame()中的SIGNAL和槽函數函數

void Widget::slotPopulateJavaScriptWindowObject()
{
    ui->webView->page()->mainFrame()->addToJavaScriptWindowObject("ReinforcePC", this);
}

進行響應。參考文獻1:《javascript調用qt》,能夠解釋這個槽函數的重要性。

  • 在WebEngine中的初始化:
QWebEnginePage *page = new QWebEnginePage(this);  // 定義一個page做爲頁面管理
QWebChannel *channel = new QWebChannel(this);     // 定義一個channel做爲和JS或HTML交互
page->load(strMapPath);                            // page上加載html路徑
page->setWebChannel(channel);                    // 把channel配置到page上,讓channel做爲其信使
ui->webEngine->setPage(page);                    // 創建page和UI上的webEngine的聯繫

若是你的 初始化程序寫到這裏,當你運行程序的時候,不管是webKits裏的WebView仍是新版的webEngineView,你的UI界面上的那個組件區域就會顯示那個html文件了。

到此,咱們完成了二者的初始化。


  • WebKits組件中的運行JS:

咱們以按鈕的槽函數爲例,當點擊按鈕時,會向JS發送命令,運行JS腳本,咱們這裏發送的是將顯示變爲衛星圖的JS命令:

void Widget::on_pushButtonStreetMap_clicked()
{
    QWebFrame *frame = ui->webView->page()->mainFrame(); // 定義一個QWebFrame負責交互
    QString cmd = QString("showStreetMap()"); // JS的命令
    frame->evaluateJavaScript(cmd);              // 使用frame下的命令運行該命令
}

從這個例子中咱們也能夠看到,QWebFrame是JS交互的關鍵。

  • WebEngine組件中的運行JS:

仍是以該槽函數爲例:

void Widget::on_pushButtonSatelliteMap_clicked()
{
    QString cmd = "showSatelliteMap()";
    ui->webEngine->page()->runJavaScript(cmd);        // 直接page()下就能夠運行
}

在JS單向通訊中十分簡單,也不須要使用QWebChannel信使,但該方法runJavaScript()沒法在構造函數中使用,緣由不明。也能夠這樣使用:

connect(ui->webEngine,&QWebEngineView::loadFinished,[=](int){
             ui->webEngine->page()->runJavaScript(cmd1);

第二個參數SIGNAL位置的,只能使用這樣的方式調用,若是使用SIGNAL(....loadFinished),報錯。

4. 總結

經過這樣的方法,咱們就完成了一個初級的過渡。本人因爲是研究嵌入式的程序員,只是上位機學習簡單的Qt作一點點當成輔助開發,並無什麼高深的Qt技術,也正在學習中,歡迎討論。

參考文獻:

[1] 在水一方著.javascript調用Qt.CSDN博客.2011-07-18.

[2]Я!ńɡ著.QT5利用chromium內核與HTML頁面交互.CNBLOGS. 2015-11-17.

[3]liuyez123著.[實現QT與HTML頁面通訊]. CSDN博客. 2016-01-13.

posted @ 2017-07-17 13:15 Carlos·Wei at Yichun

相關文章
相關標籤/搜索