当前位置:首页 > 芯闻号 > 充电吧
[导读]流程有些复杂,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
}
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

其实在 c++语言里面const修饰的才算是一个真正的常量,在 c 语言中 const 可以说是个“冒牌货”。为什么会这样?其实是 c++ 编译器对 const 进行了加强,当 c++ 编译器遇到常量声明时,不会像 c...

关键字: c++ C语言 const

返回函数的引用去初始化一个新的引用这个和前面一样,都是不会产生副本,但是现在是用返回值去初始化一个引用声明c,也就是说这时候变成了变量temp的别名,在c的生命周期内temp是一直有效的,这样做完全可以。

关键字: c++ 返回值 引用声明

C++是一种面向对象的高级程序设计语言,是C语言的超集。

关键字: c++ C语言

摘 要 :为解决制鞋行业中喷胶精度不高、灵活性差、生产效率低的问题,设计一种基于机器视觉的鞋模喷胶系统。该系统硬件由工业摄像头、工控机及路由器构成,软件则采用图像识别库 OpenCV 与图形界面应用程序开发框架 Qt 编...

关键字: 机器视觉 图像处理 鞋模 喷胶 OpenCV QT

嵌入式系统是指以应用为中心、以计算机技术为基础,软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。

关键字: QT 嵌入式 C++

摘 要:仓储作为物流与供应链的核心环节,对食品安全的控制起着至关重要的作用。温湿度是影响粮食仓储过程安全与品质的重要因素。文中使用无线传感网络进行数据采集,通过Qt平台设计软件系统,并借助数据库进行数据存储与分析处理,实...

关键字: 成品粮 仓储 温湿度监测 无线传感网络 QT

在此部件上绘制行号,并将其放置在CodeEditor的viewport()的左边距区域上,QWidget类也可以帮助我们对其内容进行滚动。

关键字: QT 代码编辑器

不管是Qt新手还是开发过qt的群体来说,对Qt Designer、Qt Quick Designer、Qt Creator这几个应用程序肯定是熟悉的。

关键字: QT IDE C

在当今社会,人们的生活水平普遍提高,工作强度越来越大,营养的过剩和运动量的减少,导致心脑血管疾病的发病率是越来越高。

关键字: Linux QT GPRS 远程集群式 心脏病人实时诊断系

qt值得学习吗? 嵌入式要学的东西真的很多,我们可能会说不写界面的话就不用学qt了?我不赞同。

关键字: 嵌入式 QT UI
关闭
关闭