• 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

  • 相关阅读:
    A/B-test
    LDA概率主题模型
    减肥经验帖
    wide and deep
    利用责任链模式设计一个拦截器
    分享几个 SpringBoot 实用的小技巧
    「造个轮子」——cicada 设计一个配置模块
    「造个轮子」——cicada 源码分析
    「造个轮子」——cicada(轻量级 WEB 框架)
    强如 Disruptor 也发生内存溢出?
  • 原文地址:https://www.cnblogs.com/owenlang/p/5972344.html
Copyright © 2020-2023  润新知