Qt WebEngine 網頁交互


環境:Qt5.7.0,VS2013

一、簡單介紹

從 Qt5.4 開始已經去掉 Qt WebKit 模塊了,使用的是 chrome 內核封裝的 QtWebEngine,瀏覽器相關的類有以下幾個:

QWebEngineCertificateError

Information about a certificate error

QWebEngineDownloadItem

Information about a download

QWebEngineFullScreenRequest

Enables accepting or rejecting requests for entering and exiting the fullscreen mode

QWebEngineHistory

Represents the history of a web engine page

QWebEngineHistoryItem

Represents one item in the history of a web engine page

QWebEnginePage

Object to view and edit web documents

QWebEngineProfile

Web engine profile shared by multiple pages

QWebEngineScript

Encapsulates a JavaScript program

QWebEngineScriptCollection

Represents a collection of user scripts

QWebEngineSettings

Object to store the settings used by QWebEnginePage

QWebEngineView

Widget that is used to view and edit web documents

為了通過在網頁和應用程序交互,需要使用另一個類 QWebChannel,它的介紹如下:

Expose QObjects to remote HTML clients.

The QWebChannel fills the gap between C++ applications and HTML/JavaScript applications. By publishing a QObject derived object to a QWebChannel and using the qwebchannel.js on the HTML side, one can transparently access properties and public slots and methods of the QObject. No manual message passing and serialization of data is required, property updates and signal emission on the C++ side get automatically transmitted to the potentially remotely running HTML clients. On the client side, a JavaScript object will be created for any published C++ QObject. It mirrors the C++ object's API and thus is intuitively useable.

The C++ QWebChannel API makes it possible to talk to any HTML client, which could run on a local or even remote machine. The only limitation is that the HTML client supports the JavaScript features used by qwebchannel.js. As such, one can interact with basically any modern HTML browser or standalone JavaScript runtime, such as node.js.

There also exists a declarative WebChannel API.

二、使用步驟

1.在 QtCreateor 中新建  Qt Widgets Application 項目,放幾個控件上去,下邊的是一個 widget,要用來顯示網頁,需要將它提升為 QWebEngineView

image

 

2.在 pro 文件中添加以下內容,注意 c++11 也是必須的

QT += webenginewidgets webchannel

CONFIG += c++11

3.從 Qt 目錄下找到 qwebchannel.js 復制到項目目錄,從 jquery 網站下載 jquery-3.1.1.min.js 到項目目錄中

4.與網頁交互的類最好從 QObject 繼承(其它也可以,但可能出問題),以下是相關文件

 1 #ifndef WEBOBJECT_H
 2 #define WEBOBJECT_H
 3 
 4 #include <QObject>
 5 
 6 class WebObject : public QObject
 7 {
 8     Q_OBJECT
 9 
10     //供網頁 JS 使用的屬性
11     Q_PROPERTY(QString name MEMBER m_name NOTIFY sig_nameChanged)
12     Q_PROPERTY(int age MEMBER m_age NOTIFY sig_ageChanged)
13 
14 public:
15     explicit WebObject(QObject *parent = 0);
16 
17     void setName(const QString& name);
18     void setAge(int age);
19 
20 signals:
21     void sig_nameChanged(const QString& name);
22     void sig_ageChanged(int age);
23 
24 public slots:    
25     //供網頁 JS 調用
26     void slot_debug(const QString& msg);
27 
28 private:
29     QString m_name;
30     int m_age;
31 };
32 
33 #endif // WEBOBJECT_H
WebObject.h
 1 #include "WebObject.h"
 2 #include <QDebug>
 3 
 4 WebObject::WebObject(QObject *parent) : QObject(parent)
 5 {
 6     m_name = "owenlang";
 7     m_age = 26;
 8 }
 9 
10 void WebObject::setName(const QString &name)
11 {
12     if (name != m_name)
13     {
14         m_name = name;
15         emit sig_nameChanged(m_name);
16     }
17 }
18 
19 void WebObject::setAge(int age)
20 {
21     if (age != m_age)
22     {
23         m_age = age;
24         emit sig_ageChanged(m_age);
25     }
26 }
27 
28 void WebObject::slot_debug(const QString& msg)
29 {
30     qDebug() << "web debug: " << msg;
31 }
WebObject.cpp
 1 #ifndef MAINWIDGET_H
 2 #define MAINWIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class MainWidget;
 8 }
 9 
10 class WebObject;
11 class MainWidget : public QWidget
12 {
13     Q_OBJECT
14 
15 public:
16     explicit MainWidget(QWidget *parent = 0);
17     ~MainWidget();
18 
19 private slots:
20     void on_okBtn_clicked();
21 
22     void on_callJsBtn_clicked();
23 
24 private:
25     Ui::MainWidget *ui;
26 
27     WebObject * m_dataObj;
28 };
29 
30 #endif // MAINWIDGET_H
MainWidget.h
 1 #include "MainWidget.h"
 2 #include "ui_mainwidget.h"
 3 #include "WebObject.h"
 4 #include <QWebChannel>
 5 
 6 MainWidget::MainWidget(QWidget *parent) :
 7     QWidget(parent),
 8     ui(new Ui::MainWidget)
 9 {
10     ui->setupUi(this);
11     ui->webView->load(QUrl("qrc:/index.html"));
12 
13     m_dataObj = new WebObject();
14 
15     //重要設置
16     QWebChannel *channel = new QWebChannel(this);
17     channel->registerObject("person", m_dataObj);
18     ui->webView->page()->setWebChannel(channel);
19 }
20 
21 MainWidget::~MainWidget()
22 {
23     delete ui;
24 }
25 
26 void MainWidget::on_okBtn_clicked()
27 {
28     bool ok;
29     QString name = ui->nameEdit->text().trimmed();
30     int age = ui->ageEdit->text().trimmed().toInt(&ok, 10);
31     if (!ok)
32     {
33         age = 0;
34     }
35 
36     m_dataObj->setName(name);
37     m_dataObj->setAge(age);
38 }
39 
40 void MainWidget::on_callJsBtn_clicked()
41 {
42     //執行網頁 JS
43     QString strJs = ui->jsEdit->toPlainText();    
44     ui->webView->page()->runJavaScript(strJs);
45 }
MainWidget.cpp

 最后是網頁 index.html,把 index.html 和 jquery,qwebchannel.js 都加入到 qrc 資料文件中

 1 <!doctype html>
 2 <html>
 3 <meta charset="utf-8">
 4 <head>
 5     <script src="jquery-3.1.1.min.js"></script>
 6     <script src="qwebchannel.js"></script>
 7 </head>
 8 
 9     <div>
10                 <span>name:</span><input type="text" id="name"/>
11                 <br/>
12                 <span>age:</span><input type="text" id="age"/>
13     </div>
14     
15     <script>
16         'use strict'; //JS 不使用嚴格模式也可以
17 
18         var updateName = function(text)
19         {
20             $("#name").val(text);
21             
22             //調用 Qt 的函數,必須是 public slots 函數
23             window.bridge.slot_debug("update name: " + text);
24         }
25 
26         var updateAge = function(text)
27         {
28             $("#age").val(text);
29             window.bridge.slot_debug("update age: " + text);
30         }
31 
32         new QWebChannel(qt.webChannelTransport, //注意 webChannelTransport 開頭字母小寫
33             function(channel){
34                 var person = channel.objects.person;
35                 window.bridge = person; //為了在其它位置使用
36                 //直接使用 QObject 派生類的屬性
37                 updateName(person.name);
38         updateAge(person.age);
39                 
40         //連接 Qt 的信號到 JS 函數
41                 person.sig_nameChanged.connect(updateName);
42         person.sig_ageChanged.connect(updateAge);
43             }
44         );
45 
46     </script>
47 </html>
index.html

 

5.運行情況

6.程序打包下載:WebEngineTest.zip

7.需要注意的是,Qt5.7.0 的網頁交互有一個 BUG,從另一個頁面跳轉到要交互的頁面后,會出現 qt not defined,這個 BUG 在 Qt5.7.1 中已修復。

https://bugreports.qt.io/browse/QTBUG-54107
https://bugreports.qt.io/browse/QTBUG-53411

https://forum.qt.io/topic/68356/qt-webenginetransport-not-available-anymore
https://forum.qt.io/topic/68869/qt-is-undefined-when-i-declare-qwebchannel/2

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM