首页 > 技术知识 > 正文

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(“Couldnt 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(“Couldnt 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”; }
<

猜你喜欢