当前位置:首页 > 芯闻号 > 充电吧
[导读]流程有些复杂,QML不支持调用很多常见的js引擎,我们可以利用webview来达到。不过在使用socket.io,发现必须要在安卓4.4版本或更高才行,这个不是安卓的问题,是最新版的Qt没有优化老版本

流程有些复杂,QML不支持调用很多常见的js引擎,我们可以利用webview来达到。不过在使用socket.io,发现必须要在安卓4.4版本或更高才行,这个不是安卓的问题,是最新版的Qt没有优化老版本的WebView,唉。
开发流程图:
从发送到回调: QML -> WEBVIEW中的socke.io  -> node.js服务器  ->WEBVIEW  -> (标注)C++ -> QML
标注:由于socket.io是异步的,QML调用JS允许有回调,但是不支持在WEBVIEW中的异步回调。因此用C++来转发。
#ifndef TQMLHELPER_H
#define TQMLHELPER_H

#include#include#includeclass TQmlHelper : public QObject
{
    Q_OBJECT
public:

    explicit TQmlHelper(QObject *parent = 0);
//    代码规范:  set开头   供QML调用  用来设置本类的QML对象
//               do开头    给HTTP服务器调用  用来间接通信QML
    Q_INVOKABLE void  setroot(QObject* obj);
    Q_INVOKABLE void  setTXL(QObject* obj);

    //从聊天服务器获取好友 请求Qml刷新好友列表
    void do_updataFlist(QByteArray& b);

signals:

public slots:

 private:
QObject*  root;

//PageTongxunlv.qml:
//Component.onCompleted: {
//        myapp.setTXL(gen);
//         console.log("cout:"+model.count);
//         model.append({name:"代码统计行数:"+model.count,tip:"代码生成的行"});
//    }
//PageTongxunlv中的跟节点 包含好友列表的一些成员函数
QObject*  gen;
};

#endif // TQMLHELPER_H
#include "tqmlhelper.h"
#include#includeTQmlHelper::TQmlHelper(QObject *parent) : QObject(parent)
{
        root = NULL;
}



void  TQmlHelper::setroot(QObject* obj)
{
    qDebug()<>>:"<< obj->objectName();
}

 void TQmlHelper::do_updataFlist(QByteArray& b)
 {
            qDebug()<<"do_updataFlist:"<<b;
            QString a = b; ;
            QMetaObject::invokeMethod(gen, "刷新好友列表", Qt::ConnectionType::BlockingQueuedConnection, Q_ARG(QVariant, a));

 }
#include"myhttp.h"
#includeextern TQmlHelper* tmphelp;
Helloworldcontroller3::Helloworldcontroller3(QObject* parent):HttpRequestHandler(parent)
{

}
#includevoid Helloworldcontroller3::service(HttpRequest &request, HttpResponse &response) {

    //允许跨域
      response.setHeader("Access-Control-Allow-Origin", "*"); 

         QByteArray path=request.getPath();
        qDebug("RequestMapper: path=%s",path.data());

        //登录状态
        if (path=="/loging") {
            QByteArray a = request.getParameter("p1");
            qDebug()<<a;

            if(a.toInt()==1)
            {
                qDebug()<<"loging ok";
            }else{
                qDebug()<<"loging erro";
            }
             response.setStatus(200,"OK");
           // HelloWorldController().service(request, response);
        }
         //获取好友列表的返回结果
        else if (path=="/Flist") {
             QByteArray a = request.getParameter("p1");
             tmphelp->do_updataFlist(a);
             response.write("ok",true);
             response.setStatus(200,"ok");
        }

        else {
            response.setStatus(404,"oo!Not found");
            QString  s =QString::fromLocal8Bit("请请不要跨域哦");
            QByteArray s2(s.toStdString().c_str());
            response.write(s2,true);
        }

        qDebug("RequestMapper: finished request");
}
*****main.qml
TQmlHelper*  tmphelp;
void  RegFunc(QQmlApplicationEngine&  engine)
{

       tmphelp = new TQmlHelper(&engine);

        engine.rootContext()->setContextProperty("myapp", (QObject*)tmphelp);
}
#includeint main(int argc, char *argv[])
{


    QApplication::setApplicationName("Myapp");
   QApplication::setOrganizationName("QtProject");
     QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);

//     qputenv("QT_SCALE_FACTOR", b);
//     system("su");
    QApplication app(argc, argv);

//    MyWait*  label = new MyWait();
//    label->show();

   //

qDebug("********开始*********");
    QSettings* listenerSettings= new QSettings("assets:/demo.ini",QSettings::IniFormat,&app);

    qDebug("config file loaded");

    listenerSettings->beginGroup("listener");

       // Start the HTTP server

       new HttpListener(listenerSettings, new Helloworldcontroller3(&app), &app);

     QQuickStyle::setStyle("Material");
    QQmlApplicationEngine engine;


   RegFunc(engine);
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
            return -1;

//    label->hide();

qDebug("********结束*********");
    return app.exec();
}
由于如果用C++主动获取QML对象,可能存在QML对象尚未初始化问题,因此,在qml初始化后调用C++来设置QML对象指针。
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Material 2.0
import QtGraphicalEffects 1.0
import QtQuick.Particles 2.0
import "Ndk.js"   as  Ndk
import "./code"
import QtWebView 1.1

 ApplicationWindow {
    id:root;
    visible: true;



     height: 480;
     width: 320;
    Component.onCompleted: {

        //把窗口对象传给Qt 之所以加载完毕后才传递 很多对象提前是无内存块
        myapp.setroot(root);

    }

    property real pixelDensity: 4.46
    property real multiplierH: root.height/480 //default multiplier, but can be changed by user
    property real multiplierW: root.width/320 //default multiplier, but can be changed by user
    function dpH(numbers) {

        return Math.round(numbers*((pixelDensity*25.4)/160)*multiplierH);
    }
    function dpW(numbers) {
        return Math.round(numbers*((pixelDensity*25.4)/160)*multiplierW);
    }
    function  dpi2(px)
    {

        return Math.round(px*((Screen.pixelDensity*25.4)/160))
    }


    /**
        * 将px值转换为dip或dp值,保证尺寸大小不变
        *
        * @param pxValue
        * @param scale
        *            (DisplayMetrics类中属性density)
        * @return
        */
    function   px2dip(pxValue) {
        var scale = myapp.getdensity();
        return  (pxValue / scale + 0.5);
    }

    property color  accentcol:"red"
    property color  backgroundcol:"white"
    property color  foregroundcol:"#000000"
    property color  primarycol:"blue"
    Material.accent:accentcol
    Material.background:backgroundcol
    Material.foreground:foregroundcol
    Material.primary: primarycol

//消息框
            MessageDialog {
                id:dlg;
                objectName: "xiaoxikuang";
                width: Screen.width;
                height: Screen.hight;
                visible: false;
                  title: "进度"
                    icon: StandardIcon.Question
                    text: "file.txt already exists.  Replace?"
                    detailedText: "To replace a file means that its existing contents will be lost. " +
                        "The file that you are copying now will be copied over it instead."
                    standardButtons: StandardButton.Yes | StandardButton.No 
            }
            function messaggeBox(title,txt)
            {
                dlg.text = txt;
                dlg.title = title;
                dlg.visible = true;
            }


//调试打印

            Item {
                visible: true
                width:parent.width;
                height:dpH(100);
                z:100

//                    color:Ndk.SDColor_warning;
                        ListView{
                            id:dbgtxt;
                            width:parent.width;
                            height:dpH(100);
                            model: ListModel{
                                id:dbgmodel;
                                ListElement{txt:"123"}
                            }
                            delegate: Label{
                                font.pixelSize: dpW(18);
                                font.bold: true;
                                color: Ndk.green_1
                                text:txt
                            }
                            displaced: Transition {
                                      NumberAnimation { properties: "x,y"; duration: 1000 }
                                  }
                            move: Transition {
                                      NumberAnimation { properties: "x,y"; duration: 1000 }
                                  }
                        }
                }
            function dbg(txt)
            {
                if(dbgmodel.count>=5)
                {
                    dbgmodel.clear();
                }
                dbgmodel.append({txt:txt});
            }


    //////////////////////加载控制器//////////////////////////
    property alias mwebview: mywebview;


            property var txtprogress_var: 0
            property var txtmainpage_var: 0
             property var txtsubpage1_var: 0
            Item {
                width: Screen.width;
                height: Screen.height
                visible: true
                z:100
                id: bk;
                Rectangle{
                    id:zezao;
                    opacity: 0.9;
                    anchors.fill: parent;
                    color:"#cccccc"
                    Column{
                        width: parent.width;
                        spacing: 2;
                        //WebView加载进度
                        Label{
                            font.pixelSize: dpW(18);
                            font.bold: true;
                            color: Ndk.文字色偏白
                            id:txtprogress
                            text:"WebKit加载进度:"+txtprogress_var
                        }

                        Rectangle{

                            anchors.margins: dpW(5);
                            width: parent.width;
                            height: dpH(20);
                            color: Ndk.SDColor_success;
                            radius: dpW(2)
                            Rectangle{
                                 radius: dpW(2)
                                property var pass: 0
                                id:bartxt;
                                width: parent.width/100*pass;
                                height: dpH(20);
                                color: Ndk.SDColor_info;
                                 Behavior on width {NumberAnimation{ easing.type: Easing.InOutBounce;duration: 2000}}
                            }

                        }

                         //mainpage加载进度
                        Label{
                            id:txtmainpage;
                            color: Ndk.文字色偏白
                            font.pixelSize: dpW(18);
                            font.bold: true;
                            text:"主页面加载进度:"+txtmainpage_var
                        }

                        Rectangle{
                            anchors.margins: dpW(5);
                            width: parent.width;
                            height: dpH(20);
                            color: Ndk.SDColor_success;
                            radius: dpW(2)
                            Rectangle{
                                 radius: dpW(2)
                                property var pass: 0
                                id:barmainpage;
                                width: parent.width/100*pass;
                                height: dpH(20);
                                color: Ndk.SDColor_info;
                                 Behavior on width {NumberAnimation{ easing.type: Easing.InOutBounce;duration: 2000}}
                            }
                        }

                        //子页面加载进度
                        Label{
                            id:txtsubpage1;
                            color: Ndk.文字色偏白
                            font.pixelSize: dpW(18);
                            font.bold: true;
                            text:"首页加载进度:"+txtmainpage_var
                        }

                        Rectangle{
                            anchors.margins: dpW(5);
                            width: parent.width;
                            height: dpH(20);
                            color: Ndk.SDColor_success;
                            radius: dpW(2)
                            Rectangle{
                                 radius: dpW(2)
                                property var pass: 0
                                id:barsubpage1;
                                width: parent.width/100*pass;
                                height: dpH(20);
                                color: Ndk.SDColor_info;
                                 Behavior on width {NumberAnimation{ easing.type: Easing.InOutBounce;duration: 2000}}
                            }
                        }

                    }

                    Behavior on opacity {
                      NumberAnimation{ easing.type: Easing.InOutBounce;duration: 2000}

                    }
                    onOpacityChanged: {
                        if(opacity==0)
                        {
                            bk.visible = false;
                            bk.deleteLater();
                            dbg("onOpacityChanged");
                        }
                    }
                }
                // 禁止事件穿透
                   MouseArea{
                       anchors.fill: parent;
                       onPressed:{
                            mouse.accepted = true
                       }
                     //  drag.target: root  // root可拖动
                   }
                   //外部调用刷新更新状态 并且判断是否全部加载成功
                function changgepro(type,pro)
                {
                    if(type == 0)//webview加载进度
                    {
                        bartxt.pass = pro;
                        txtprogress_var = pro;
                    }else  if(type == 1)//mainpage加载进度
                    {
                         barmainpage.pass = pro;
                        txtmainpage_var = pro;
                    }else  if(type == 2)//mainpage加载进度
                    {
                         barsubpage1.pass = pro;
                        txtsubpage1_var = pro;
                    }
                    if(txtprogress_var == 100  && txtmainpage_var == 100 && txtsubpage1_var ==100)
                    {
                        oninitOk();

                    }
                }
                //前台页面加载完毕后的行为
                function oninitOk()
                {
                    foot.visible = true;
                    zezao.opacity = 0;
                     benavShow = true;
                    messaggeBox("状态","加载完毕");
//                     bk.visible = false;
                }



            }


    WebView{
        //加载完毕 loading变成false
        visible: false;
        id:mywebview;
        objectName: "webview"
          url:"file:///android_asset/index.html";
        onLoadProgressChanged: {

//                txtprogress.text="WebKit加载进度:"+mywebview.loadProgress;
             bk.changgepro(0,mywebview.loadProgress);
        }
        onLoadingChanged: {

        }
    }

    //页头
    property alias roothd: hd
     header: ToolBar{
        id:hd;
        states: [
            State {
                name: "hide"
                PropertyChanges {
                    target: hd;opacity:0;height:0;width:0;
                }
                PropertyChanges {
                    target: lisetview;opacity:0;rotation:360;height:0;
                }
            }
        ]

        transitions: Transition {
            // Make the state changes smooth
            ParallelAnimation {
                NumberAnimation { duration: 500; properties: "opacity,x,contentY,height,width" }
                ColorAnimation { property: "color"; duration: 888 }
                NumberAnimation { duration: 888; properties: "rotation" }


            }
        }


        height:dpH(60);
        Text{
            text:"mywebview.loadProgress+"
            anchors.centerIn: parent
            color: "white"
            font.pixelSize: dpW(18)
        }

        layer.enabled: true
        layer.effect: DropShadow {
            transparentBorder: true//绘制边框阴影
            color: "#000000";
            radius: dpH(15)
            id:drop;

            //cached: true;
            horizontalOffset: 0;
            verticalOffset: 0;
            samples: 16;
            smooth: true;


        }
    }

    function  getdpistype()
    { 
        console.log("SCALA: "+Screen.pixelDensity*25.4/160)
        console.log(Screen.pixelDensity)
        var curdpi = Screen.pixelDensity*25.4;
        var  mydpi = curdpi.toFixed(0);
        console.log(mydpi);
        console.log("my dpi "+myapp.getdpi())
        return "MYDPI+"+mydpi;
        if(mydpi>=480)
        {
            console.log("XXHDPI");
            return "XXHDPI";
        }else  if(mydpi>=320)
        {
            console.log("XHDPI");
            return "XHDPI";
        }else  if(mydpi>=240)
        {
            console.log("HDPI");
            return "HDPI";
        }else  if(mydpi>=180)
        {
            console.log("MDPI");
            return "MDPI";
        }else
        {
            console.log("LDPI");
            return "LDPI";
        }


    }
    Loader{
        id:mainpage;
        asynchronous: true
        anchors.fill: parent;
        sourceComponent: commapnpage;
        onProgressChanged: {
            bk.changgepro(1,progress*100);

        }

    }
    Component{
        id:commapnpage;
        SwipeView{
            state: "hide1"
            currentIndex: tabindex

            onCurrentIndexChanged: {
                console.log("onCurrentIndexChanged:"+currentIndex);
                tabindex = currentIndex;//导航栏的序号与这里同步,手动滑动触发这里
                if(currentIndex==1)
                {
                    tongxinlu.item.获取好友列表();
                }

            }


            //首页
            Page{

                id:gouzhen;
                Loader{
                    id:shouye
                     asynchronous: true//异步加载组件
                     anchors.fill: parent
                    sourceComponent: Page_gouzhen{}
                    onProgressChanged: {
                        bk.changgepro(2,shouye.progress*100);
                    }


                }
            }
        //通讯录
            Page{
                id:tongxun;
                Loader{
                  asynchronous: true
                    id:tongxinlu;
                     anchors.fill: parent;
                    sourceComponent: PageTongxunlv{}

                }
            }



        }
    }

    //当前选中的导航序号
   property var  benavShow  :false;//是否显示底部导航
    property int tabindex: mainpage.item.currentIndex
    footer: Row{
        visible: benavShow;

        id:foot;
        width:benavShow? parent.width:0;
        height:benavShow? width/5*0.75:0;

        Repeater{
            id:rep
            delegate: NavNewDelegate{
                width: benavShow?parent.width/5:0;
                height:benavShow?width*0.75:0;
                rotation:benavShow?0:Math.random()*360
                id:navitem;
               Behavior on width {NumberAnimation {duration: 2000; easing.type: Easing.InOutQuad}}
               Behavior on height {NumberAnimation {duration: 2000; easing.type: Easing.InOutQuad}}
               Behavior on rotation {NumberAnimation {duration: 2000; easing.type: Easing.InOutQuad}}

               onClick: {
                    dbg("Delegate传递过来的下标:"+index+tabindex);
                    console.log("Delegate传递过来的下标:"+index+tabindex);

                }

            }
            model:NavNewModel{id:model1}
        }
    }
    Keys.enabled: true;
    Keys.onReleased:  {
        console.log("key"+event.key);
        if(event.key==Qt.Key_Back)
        {
            console.log("back");
        }
    }
}
****关键代码  QML和C++以及webview中的js库交互的部分
import QtQuick 2.7
import QtQuick.Controls 1.4 as Old
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Universal 2.0
import QtGraphicalEffects 1.0
import QtQuick.Particles 2.0
import QtWebSockets 1.0
import "../"
Item {
    property alias mview: view
    objectName: "FList";
        anchors.fill: parent;
        id:gen;
        ListView{
            id:view;

             anchors.fill: parent;
            delegate: ListTongxunlvDelegate{
            }
            model: ListTongxunlvModel{
                id:model;
            }
            Component.onCompleted: {
                    myapp.setTXL(gen);
                     console.log("cout:"+model.count);
                     model.append({name:"代码统计行数:"+model.count,tip:"代码生成的行"});
                }
        }

        //专门被C++调用的函数
        function 刷新好友列表(x)
        {
            console.log("get c++ *****"+x)
            root.messaggeBox("刷新好友列表:",x);

        }

    function 获取好友列表()
    {

        mywebview.runJavaScript("获取好友列表()",function(result){
            for(var x in  result)
            {
                root.dbg(result[x]);
            }
             root.dbg(result);


        });
    }



}
**********HTML代码 使用裸页面只为加载JS功能
h
*****js代码
var msocket;
mui.init({})
mui.ready(lod);
function   登录成功(arg1)
{
//  $.post("http://localhost:8080/loging?p1="+arg1, function(data){
//      alert("Data Loaded: " + data.name);
//  },"json");
 $.post("http://localhost:8080/loging?p1="+arg1);
}
function   发送到C加加(path,arg1)
{
//  $.post("http://localhost:8080/loging?p1="+arg1, function(data){
//      alert("Data Loaded: " + data.name);
//  },"json");
  $.post("http://localhost:8080/"+path+"?p1="+arg1);
}
var  isloging = false;
function  lod(){


        alert("ok");

        console.log("模拟器连接");
//          msocket = io.connect('ws://10.0.2.2:8081', { 'reconnect': true });//模拟器访问局域网
        msocket = io.connect('ws://192.168.0.101:8081', { 'reconnect': true });//模拟器访问局域网

        msocket.on('connect',function(){
            alert("连接成功;");
            isloging = true;
            msocket.emit("denglu","admin","123",function(callbackdata){

                alert("登录结果:"+callbackdata);
            })
            登录成功(1);

        });


    //正在连接
    msocket.on('connecting',function(){
        alert("正在连接");
    });

    //连接超时
    msocket.on('connect_timeout',function(){
        console.log("connect_timeout");
    });


    //连接失败
    msocket.on('connect_failed',function(){
        alert("连接失败");
    });

    //错误发生 并且无法被其他事件类型所处理
    msocket.on('error',function(data){
        alert("错误发生 并且无法被其他事件类型所处理");

    });



    //重连失败
    msocket.on('reconnect_failed',function(){
        alert("reconnect_failed");
    });

    //成功重连
    msocket.on('reconnect',function(TheNumber){
        alert("reconnectOk"+TheNumber);
    });

    //正在重连
    msocket.on('reconnecting',function(TheNumber){
        console.log("reconnecting"+TheNumber);

    });


}


function  Testfunc()
{
//  alert("get")
    return 123;
}
//对应QML代码:
//function 获取好友列表()
//    {
//
 //       mywebview.runJavaScript("获取好友列表()",function(result){
//            for(var x in  result)
//            {
  //              root.dbg(result[x]);
  //          }
 //            root.dbg(result);
//
//
//        });
  //  }
var  mdata;
function 获取好友列表()
{

    if(isloging==false)
    {
        alert("暂未登录,无法拉取好友");
        return "";
    } 
        alert("获取好友中");



             msocket.emit("获取好友",/*"获取好友",*/function(data){
        //传过来的是字符串 不需要转换了  交给QtQuick转换吧 一样
        //不对 貌似qtquick可以直接解析对象
        console.log(data)
        发送到C加加("Flist",data);

        mdata = data;
//      console.log(JSON.parse(data))
            });

    //由于是异步的 因此可能先返回了 才接收到服务器发过来的数据 解决方式很多 这里用同步方式
    alert("最后层返回");
    return mdata;//此返回值无用 真正的返回值是由服务器转发过来经过 发送到C加加("Flist",data) 转发给QML
}
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭