Qt混合式开发

小王子🤴 2020-09-13 21:35:31 4082
Qt混合式开发
一、简介

本片文章简单的来介绍Qt中混合式开发。
首先说明下什么是混合式开发,混合式开发简单的来说就是原生+H5开发,由两部分组成:原生应用客户端与H5网页,原生应用客户端为H5网页提供运行框架与为支持,H5实现界面展示与程序业务。
混合式开发的优点:
1、开发效率高,节约时间。同一套代码Android和IOS基本上都可使用;
2、更新和部署比较方便,每次升级版本只需要在服务器端升级即可;
3、代码维护方便、版本更新快,节省产品成本;
4、比web版实现功能多;
5、可离线运行。

二、Qt混合式开发介绍

混合式开发的主要内容是在原生的框架上加载h5网页和原生与js交互。
Qt加载网页:
使用QWebEngineView加载网页。
//定义QWebEngineView 对象
QWebEngineView webview = new QWebEngineView();
//加载网页
webview ->page()->load(QUrl(“https://www.baidu.com”));
与Js交互:
使用QWebChannel与Js交互。
网上找的一些与Js的交互的方法都需要在js文件中加载“qwebchannel.js”(Qt安装目录中可以找到)文件和添加如下方法:
// QT交互
new QWebChannel(qt.webChannelTransport, function(channel) { window.bridgeJS = channel.objects.bridge; });
但是如果这样的话就需要前端开发人员开发Js是加入这句话和需要打包“qwebchannel.js”到前端文件中,这样的话每次第一次和前端人员定交互接口时就需要和他们说明,很是麻烦,所以我找到了一个方法,在原生的代码中以脚本的形式注入网页中,这样的话就不需要前端开发人员为了Qt专门添加上述代码。
QWebChannel
channel = new QWebChannel();
//读取qwebchannel.js文件
QFile webChannelJsFile("qwebchannel.js");
if( !webChannelJsFile.open(QIODevice::ReadOnly) ) {
qDebug() << QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString());
}
else {
qDebug() << "OK webEngineProfile";
QByteArray webChannelJs = webChannelJsFile.readAll();
//添加new QWebChannel(qt.webChannelTransport, function(channel);
webChannelJs.append(
"\n"
"var workoutCreator"
"\n"
"new QWebChannel(qt.webChannelTransport, function(channel) {"
" window.bridge_js = channel.objects.bridge_name; "
"});"
"\n"
"function enableSaveButton(forceOff) {"
"if (forceOff) {$('#btn-save-workout').prop('disabled', true);return;}"
"var nameValue = $('#name-workout').val();"
"var planValue = $('#plan-workout').val();"
"var creatorValue = $('#creator-workout').val();"
"if (nameValue.length > 0 && creatorValue.length > 0 && planValue.length > 0) {$('#btn-save-workout').prop('disabled', false);}"
"else {$('#btn-save-workout').prop('disabled', true);}"
"}"
);

//创建QWebEngineScript对象,(QWebEngineScript类封装了一个JavaScript程序。)
QWebEngineScript script;
script.setSourceCode(webChannelJs);//设置源码webChannelJs
script.setName("qwebchannel.js");//设置名称
script.setWorldId(QWebEngineScript::MainWorld);//设置world id QWebEngineScript::MainWorld:网页内容使用的世界。在某些情况下,向Web内容公开自定义功能可能很有用。
script.setInjectionPoint(QWebEngineScript::DocumentCreation);//将脚本的执行点设置为一旦创建文档,脚本将立即执行。
script.setRunsOnSubFrames(false);//不在子框架运行
// profile->scripts()->insert(script);
//创建web引擎页对象
QWebEnginePage *myPage = new QWebEnginePage(profile,this);
this->setPage(myPage);//设置web引擎页
myPage->scripts().insert(script);//添加脚本

channel = new QWebChannel(); //创建通道对象用于与JS交互
//注册交互对象
channel->registerObject("bridge_name",this);
// 这里注册对象名"name"需要与JS函数用到的名称一致
this->page()->setWebChannel(channel);
}
}
Js调用原生的接口必须是公共的槽函数。
原生调用Js接口:
//“update()”为Js接口
Webview->page()->runJavaScript(“update()”);

三、封装的web类

以下是我自己封装的web类

#ifndef QWEBVIEW_H
#define QWEBVIEW_H
#include <QtWebEngineWidgets/QWebEngineView>
#include <QtWebChannel/QtWebChannel>
#include <QWebEngineProfile>
#include <QWebEngineScript>
#include <QWebEngineScriptCollection>
#include <QDebug>
#include <QtBluetooth/QBluetoothAddress>
#include <QJsonObject>
#include <QJsonArray>
#include <QMenu>
#include <QWebEngineSettings>
class QWebview : public QWebEngineView
{
    Q_OBJECT
public:
    QWebview(QString sUrl,QWidget *parent = nullptr);
    ~QWebview() override;

public slots:
//js调用原生的接口
    void getInfo();
QWebChannel* channel = nullptr;
QString strUrl;
};

#endif // QWEBVIEW_H

#include "qwebview.h"
#include "qbridge.h"
QWebview::QWebview(QString sUrl, QWidget *parent):QWebEngineView(parent)
{
     {
        QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); //获取Web引擎默认配置文件。
        //读取qwebchannel.js文件
        QFile webChannelJsFile("qwebchannel.js");
        if(  !webChannelJsFile.open(QIODevice::ReadOnly) ) {
            qDebug() << QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString());
        }
        else {
            qDebug() << "OK webEngineProfile";
            QByteArray webChannelJs = webChannelJsFile.readAll();
            //添加new QWebChannel(qt.webChannelTransport, function(channel);
            webChannelJs.append(
                        "\n"
                        "var workoutCreator"
                        "\n"
                        "new QWebChannel(qt.webChannelTransport, function(channel) {"
                        "     window.bridge_js = channel.objects.bridge_name;  "
                        "});"
                        "\n"
                        "function enableSaveButton(forceOff) {"
                        "if (forceOff) {$('#btn-save-workout').prop('disabled', true);return;}"
                        "var nameValue = $('#name-workout').val();"
                        "var planValue =   $('#plan-workout').val();"
                        "var creatorValue = $('#creator-workout').val();"
                        "if (nameValue.length > 0 && creatorValue.length > 0 && planValue.length > 0) {$('#btn-save-workout').prop('disabled', false);}"
                        "else {$('#btn-save-workout').prop('disabled', true);}"
                        "}"
                        );

            //创建QWebEngineScript对象,(QWebEngineScript类封装了一个JavaScript程序。)
            QWebEngineScript script;
            script.setSourceCode(webChannelJs);//设置源码webChannelJs
            script.setName("qwebchannel.js");//设置名称
            script.setWorldId(QWebEngineScript::MainWorld);//设置world id  QWebEngineScript::MainWorld:网页内容使用的世界。在某些情况下,向Web内容公开自定义功能可能很有用。
            script.setInjectionPoint(QWebEngineScript::DocumentCreation);//将脚本的执行点设置为一旦创建文档,脚本将立即执行。
            script.setRunsOnSubFrames(false);//不在子框架运行
//                    profile->scripts()->insert(script);
            //创建web引擎页对象
            QWebEnginePage *myPage = new QWebEnginePage(profile,this);
            this->setPage(myPage);//设置web引擎页
            myPage->scripts().insert(script);//添加脚本
            channel = new QWebChannel();   //创建通道对象用于与JS交互
        channel->registerObject("bridge_name",this/*reinterpret_cast<QObject*>(QBridge::getBridge())*/);
            // 这里注册对象名"name"需要与JS函数用到的名称一致
            this->page()->setWebChannel(channel);
        }
    }

    strUrl = sUrl;
    this->page()->load(QUrl(sUrl));

    this->settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
    //这就实现了JS调用C++函数,实现网页向QT传递数据
    this->page()->setBackgroundColor(QColor(255,255,255,0));
}

QWebview::~QWebview()
{
    qDebug() << "QWebview::~QWebview()";
    delete  channel;
    channel = nullptr;
}
void QWebview::getInfo()
{
    qDebug() << "getAllSensorInfo";
}
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 2 收藏 评论 打赏
评论
1个
内容存在敏感词
手气红包
  • Acker 2020-09-18 10:32:22
    回复

    大神,有问题想请教您,方便加一个微信吗?

相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
小王子🤴
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区