qt之qml与C++数据交互

12 篇文章 4 订阅

qt之qml与C++数据交互

qml界面和c++界面之间传递数据

qml与c++之间的交互天然的与flux架构一致。可以直接套用,所有的事件通过信号进行分发。与android的EventBus差不多。

qml传递数据给c++

一般用于传递qml【View】上面的一些操作。比方说点击事件,请求发起事件等等。

我使用的方式是,统一交给ActionCrateor.qml进行分发,这里涉及qml的单例方式,可以看这篇文章 要记得单例的使用要使用相对路径,比方说我本地的代码结构是

代码结构
所以在别的目录里面使用就需要使用相对路径

// /a/b/xxx.qml  相对于 /action/XActionCreator.qml的位置

import “…/…/action”

为了保持一致,我这边都是使用json进行传递,而不使用对象类型进行传递

//qmldir

singleton ActionCreator 1.0 XActionCreator.qml
singleton Constant 1.0 Constant.qml

// XActionCreator.qml

pragma Singleton
import QtQuick 2.0
import SigDispatcher 1.0

Item {
    //"send_xxx(作用)" 命名的规则

    //发送事件
    function send_initData(){
        //统一发送
        //调用某个对象的信号
        dispatcher.sendEvent("active","");
    }

    //切换专辑,重新请求
    function send_getAlbumData(param){
        //param 参数,请求参数,页数?cid?
        dispatcher.sendEvent("album_get_new",param);
    }
    //c++的对象
    SigDispatcher{
        id:dispatcher
    }

}

此时需要在主入口处加上SigDispatcher

    qmlRegisterType <SigDispatcher> ("SigDispatcher", 1, 0, "SigDispatcher");
准备
//SigDispatcher.h

#ifndef SIG_DISPATCHER_H
#define SIG_DISPATCHER_H
#include <QObject>
#include <QString>
#include <QHash>
#include <QVector>
#include <QVariant>

#include "sig/signalreceiver.h"

class SigDispatcher : public QObject
{
    Q_OBJECT
public:
    explicit SigDispatcher(QObject *parent = 0);

    //注册事件
    static void addRegister(SignalReceiver * );
    static void removeRegister(SignalReceiver *);
    static void removeAll();
signals:

public slots:
    void sendEvent(QString cmd,const QVariant&);

private:
    //命令,遍历获取是否支持该命令字
    static QVector<SignalReceiver *> registers;
    //QHash<void*,QString> registers;
};

#endif // SIG_DISPATCHER_H

//SigDispatcher.cpp

#include "sigdispatcher.h"
#include "txz_common.h"

//SigDispatcher::registers = new  QVector<SignalReceiver *>();

QVector<SignalReceiver *> SigDispatcher::registers;

SigDispatcher::SigDispatcher(QObject *parent) : QObject(parent)
{
}

void SigDispatcher::addRegister(SignalReceiver * regiseter)
{
    registers.append(regiseter);
}

void SigDispatcher::removeRegister(SignalReceiver *regiseter)
{
    registers.removeAll(regiseter);
}

void SigDispatcher::removeAll()
{
    registers.clear();
}

void SigDispatcher::sendEvent(QString cmd,const QVariant& data)
{

    //auto_ptr<SigDispatcher> i(new SigDispatcher);
    for(SignalReceiver* iter:registers){
        if(iter->needInvoke(cmd.toStdString())){
            TXZ_LOGD("transform cmd: %s ,params: %s",cmd.toStdString().c_str(),data.toString().toStdString().c_str());
            //需要处理这个事件
            iter->invoke(cmd.toStdString(),(void*)(data.toString().toStdString().c_str()));
        }
    }
}

//SignalReceiver.h

#ifndef SIGNALRECEIVER_H
#define SIGNALRECEIVER_H

#include <string>
#include <list>
class SignalReceiver
{
public:
    SignalReceiver(){

    }

public:
    /**
     * @brief 是否需要拦截
     * @param cmd
     * @return
     */
    bool needInvoke(std::string cmd){
        std::list<std::string>::iterator j;
        //遍历
        for(j = cmds.begin();j!= cmds.end();j++){
            if(*j == cmd){
                return true;
            }
        }
        return false;
    }

    /**
     * @brief 处理,
     * @param cmd
     * @param data
     */
    virtual void invoke(std::string cmd,void * data) =0;
protected:
    std::list<std::string> cmds;
};

#endif // SIGNALRECEIVER_H


c++接收数据

以上就可以将所有的qml传递的信息全部转换成c++可以识别的void*,如果你传递的是json则需要进行转换,如下(其中的json.h是网上找的json的源码)【如果集成有问题,可以给我留言,我把我这边的json.h提供出来】

//AlbumModel.cpp

#include "json.h"

void AlbumModel::invoke(std::string cmd, void *data)
{
    TXZ_LOGD("cmd:%s",cmd.c_str());

    if(cmd == strCmdAlbumMore){

    }else if (cmd == strCmdAlbumNew){
        //两次的cid不同才需要响应

        TXZ_LOGD("data:%s",(char*)(data));
        startRequestData(std::string((char*)(data)));
    }
}

void AlbumModel::startRequestData(std::string param)
{
    //填写参数
    Json::Value recvJson;
    Json::Reader().parse(param,recvJson, false); //str to json
    //Json::Reader().parse(str.toStdString().c_str(),str.toStdString().c_str()+str.toStdString().length(),recvJson, false); //char* to json
    //std::string stdStr = Json::FastWriter::writeFast(recvJson); //json to str
    //可以使用qml传递过来的值了。
    TXZ_LOGD("json:%d",recvJson["cid"].asInt());
}

qml发送数据

qml怎么传递json过去呢?这里也是我踩得一个坑。

//a.qml

import "../../action"

Item{
    property var currentCid: -1
    //加载专辑数据
    function loadAlbum(cid){
        currentCid = cid;
        console.log("loadAlbum:",cid)
        //这里注意不用加双引号,js的语法,声明json的方式
        var data = {
            cid:cid
        }
        //这里注意要使用JSON.stringify
        ActionCreator.send_getAlbumData(JSON.stringify(data))
    }
}

c++传递数据给到qml

传递给qml的类型必须是QXXX的,eg: QString,QJsonArray,QJsonObject 否则传递不到,这里注意一下

准备

需要传递数据则需要在qml中绑定c++的事件,如下

//main.cpp

 QQmlApplicationEngine engine;
 //将c++对象传递给qml进行使用
 engine.rootContext()->setContextProperty("$resultActionType", &(ResultActionType::getInstance()));
//ResultActionType.h

#ifndef RESULTACTIONTYPE_H
#define RESULTACTIONTYPE_H

#include <QObject>
#include <QVariant>
#include <QJsonArray>
#include <QJsonObject>
#include <QString>
#include "base_type.h"
class ResultActionType : public QObject
{
    Q_OBJECT
private:
    explicit ResultActionType(QObject *parent = 0);

public:
    //单例
    static ResultActionType& getInstance();

signals:
    //激活
    void sig_active_success();
    void sig_active_error(int);

    //分类
    void sig_get_category_success(QJsonArray);
    void sig_get_category_error(int);

    //专辑
    void sig_get_album_success(QJsonArray);
    void sig_get_album_error(int);

    //专辑详情

    //音频
    void sig_get_audio_success(QJsonArray);
    void sig_get_audio_error(int);

    //音频详情
    void sig_get_audio_info_success(QJsonObject);
    void sig_get_audio_info_error(int);
    void sig_get_current_progress(QString,QString,QString,QString);
    void sig_get_current_status(int);
    void sig_get_notify_current_play_list(int ,QJsonArray);

    //搜索


public slots:
};

#endif // RESULTACTIONTYPE_H

#include "resultactiontype.h"
#include <QDebug>


ResultActionType::ResultActionType(QObject *parent):QObject(parent)
{

}

//这里要注意单例的写法:
ResultActionType& ResultActionType::getInstance()
{
    static ResultActionType resultActionType;
    return resultActionType;
}

qml接收数据并展示

Item{
    Component.onDestruction: {
        console.log("onDestruction")
        //解绑
        $resultActionType.sig_get_audio_info_success.disconnect(showAudioInfo);
        $resultActionType.sig_get_album_error.disconnect(retryAudioInfo);
        $resultActionType.sig_get_current_progress.disconnect(showProgress);
        $resultActionType.sig_get_current_status.disconnect(showStatus);
        $resultActionType.sig_get_notify_current_play_list.disconnect(getPlayList);
    }
    
    Component.onCompleted: {
        playAudio(viewData[1])

        //绑定监听
        $resultActionType.sig_get_audio_info_success.connect(showAudioInfo);
        $resultActionType.sig_get_album_error.connect(retryAudioInfo);
        $resultActionType.sig_get_current_progress.connect(showProgress);
        $resultActionType.sig_get_current_status.connect(showStatus);
        $resultActionType.sig_get_notify_current_play_list.connect(getPlayList);
        //
    }

    ListView {
        id: listView
        width: parent.width/2-50
        height: parent.height
        delegate: Item {
            x: 5
            width: parent.width
            height: 40
            Text {
                id: tvPlayListAudioName
                text: audioName
            }
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    console.log("hello world",index);
                    //点击播放
                    if(currentAudioId !== playList[index].audioId){
                        playAudio(playList[index].audioId);
                    }

                }
            }
        }
        model: ListModel {
            id:playlistDataListModel
        }
    }

//这里举一个例子,还有其他的类似showAudioInfo,retryAudioInfo,showProgress,showStatus
    function getPlayList(type,playlistData){
        for (var i=0; i<playlistData.length; i++){
            playlistDataListModel.append(playlistData[i])
        }
    }
}

           
           

note: 上面的getPlayList方法里面的playlistData是一个json所以传递个ListModel的时候需要有相应的key才能显示出来,比方说上面的例子中ListView中的delegate 里面的tvPlayListAudioName 需要名为audioName的key来显示数据,注意此时的playlistDataListModel如果指定了不同Key的ListElement会导致显示不出来。

C++发数据
#include <QJsonObject>
#include "resultactiontype.h"

// 显示音频播单
void _show_play_list_info() {
    int size = 10;
    //创建QJsonArray进行传递
    QJsonArray jsonArray;
    for(int i = 0; i < size; i++) {
        QJsonObject object;
        object.insert("audioName","hello");
        jsonArray.append(object);
    }

    emit ResultActionType::getInstance().sig_get_notify_current_play_list(type,jsonArray);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值