qml c++混合编程 天气插件例子

本文的demo中列举了
在这里插入图片描述
1、如何将c++对象导入qml从而解决qml调用c++接口传递数据即qml==>>c++的问题;
2、通过建立信号槽的方式解决c++通知qml层并调用qml函数及往qml传递数据即 c++==>qml的问题.

主要功能:
天气插件,实现显示及更新气象的功能。

:~/weather$ tree
.
├── deployment.pri
├── main.cpp
├── main.qml
├── qml.qrc
├── Res
│   ├── 0.png
│   ├── 1.png
│   ├── 2.png
│   ├── 3ddemo.png
│   ├── 3.png
│   ├── 3rdparty2.png
│   ├── 4.png
│   ├── 5.png
│   ├── 6.png
│   ├── 7.png
│   ├── 8.png
│   ├── 9.png
├── res.qrc
├── weather.pro
├── weather.pro.user
├── Weather.qml
├── weatherwindow.cpp
└── weatherwindow.h

在这里插入图片描述
效果:

1、将c++对象导入qml
setContextProperty(STRING_WND, weatherWdn);
对象使用字符串STRING_WND="weatherwindow"作为代理成为qml的一个节点。id为该字符串weatherwindow

    weatherWindow *weatherWdn = new weatherWindow;
    QQmlApplicationEngine engine;
    //拿到根节点
    QQmlContext *context = engine.rootContext();
    if (context == NULL) {
        qDebug( "QQmlContext is NULL \r\n");
        return false;
    }
    //将对象名导入qml上下文
    context->setContextProperty(STRING_WND, weatherWdn);
    //setContextProperty需要在engine.load qml前面才能导入成功
    engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 

2、qml通过对象访问c++
(1)成员变量需要用

Q_PROPERTY(int xpos READ xpos WRITE setXpos)

生命实现READ和WRITE方法(可在c++中调用这些方法也可在qml中调用),还有其他属性自行百度。
(2)类方法要用

Q_INVOKABLE void setXpos(const int xpos);

Q_INVOKABLE 修饰。
以上要满足继承public QObject并且声明Q_OBJECT宏
如下:

        MouseArea{
            anchors.fill: parent
            onClicked: {
            	//直接调用成员变量获取他们的值
                console.log("weatherwindow x :"+weatherwindow.xpos)
                console.log("weatherwindow y :"+weatherwindow.ypos)
                console.log("weatherwindow w :"+weatherwindow.width)
                console.log("weatherwindow h :"+weatherwindow.height)
                console.log("weatherwindow textEn :"+weatherwindow.textEn)
                //调用对象的函数获取值
                console.log("weatherwindow getTextEn() :"+weatherwindow.getTextEn())
            }
        }

3、c++快速访问qml
(1)在类中声明signal

signals:
    void appItemClicked(int);
    void sendMsgToQml(QVariant msg, QVariant wParam, QVariant lParam);
    void sendLoaderEvent();

(2)qml中声明onSendMsgToQml槽并用Connections绑定信号槽target是导入的对象字符串字段"weatherwindow" 他是对象节点的代理id。
这样c++中emit sendMsgToQml 就可以向qml中传递数据和调用qml的函数了。

 Connections {
        target: weatherwindow
        onSendMsgToQml: {
            switch (msg) {
                case first_page_language:
                    first_page_language_id=wParam;
                    console.log("update language:"+wParam);
                    break;
                case first_page_timeformat:
                    console.log("update timeformat:"+wParam);
                    switch(wParam)
                    {
                    case time_format_12H:
                        cur_time_format = time_format_12H;
                        break;
                    case time_format_24H:
                        cur_time_format = time_format_24H;
                        break;
                    default:
                        break;
                    }
                    updatelocaltime();
                    break;
                case first_page_weather:
                    console.log("update weather:"+wParam);
                    switch(wParam)
                    {
                    case weather_city:
                        console.log("update weather:city"+lParam);
                        textCity.text = lParam;
                        break;
                    case weather_weather:
                        console.log("update weather:weather"+lParam);
                        textWeather.text = lParam;
                        break;
                    case weather_temp:
                        console.log("update weather:temp"+lParam);
                        textTemp.text = lParam;
                        break;
                    }
                    break;
                default:
                    break;
            }
        }
    }

4、c++直接访问qml函数
cpp

    QObject* root = engine.rootObjects().first();
    QObject* pctrlobj = root->findChild<QObject*>("pageProgress");
    if(pctrlobj)
    {
        qDebug("home ui get  pctrlobj!!!");
        QVariant msg="home ui get  pctrlobj";
		//调用qml中的hideRear函数,并传参
        QMetaObject::invokeMethod(pctrlobj,"hideRear",Q_ARG(QVariant,msg));
    }

qml

    Item {
       id: test
       objectName: "pageProgress"
       function hideRear(msg)
       {
           console.log("hideRear $$$$$$$$$$$$$$ "+msg)
           return "some return"
       }
    }

5、qml中将c++函数封装成qml function导出到base qml 方便其他

    function timezoneClicked()
    {
        weatherwindow.timezoneClicked();
    }

    function weatherzoneClicked()
    {
        weatherwindow.weatherzoneClicked(2);
    }

6、qml发送信号到c++槽
为了比较高效的调用c++函数,可以在c++类接口中加入信号,并通过Q_INVOKABLE类方法emit该信号。从而达到qml发送信号到c++槽的作用。

7、log打印

qml: update weather:0
qml: update weather:city广州
weatherWindow::emit sendMsgToQml(ID_WEATHER, WEATHER_CITY

qml: update weather:1
qml: update weather:weather多云
weatherWindow::emit sendMsgToQml(ID_WEATHER, WEATHER_WEATHER

qml: update weather:2
qml: update weather:temp26℃
weatherWindow::emit sendMsgToQml(ID_WEATHER, WEATHER_TEMP)

home ui get  pctrlobj!!!
qml: hideRear $$$$$$$$$$$$$$ home ui get  pctrlobj

qml: weatherwindow x :200
qml: weatherwindow y :300
qml: weatherwindow w :360
qml: weatherwindow h :500
qml: weatherwindow textEn :weatherWindow
qml: weatherwindow getTextEn() :weatherWindow

贴出核心demo:
weatherwindow.h

#ifndef WEATHERWINDOW_H
#define WEATHERWINDOW_H

#include <QObject>
#include <QTime>
#include <QDate>
#include <QQmlContext>

#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QWindow>

enum {
    WEATHER_CITY,
    WEATHER_WEATHER,
    WEATHER_TEMP,
};

class weatherWindow : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int xpos READ xpos WRITE setXpos)
    Q_PROPERTY(int ypos READ ypos WRITE setYpos)
    Q_PROPERTY(int width READ width WRITE setWidth)
    Q_PROPERTY(int height READ height WRITE setHeight)
    Q_PROPERTY(QString textEn READ getTextEn WRITE setTextEn)
    Q_PROPERTY(QString textZh READ getTextZh WRITE setTextZh)
    Q_PROPERTY(QString normalPicpath READ getNormalPicPath WRITE setNormalPicPath)
    Q_PROPERTY(QString text READ getText WRITE setText)
    Q_PROPERTY(bool visible READ isVisible WRITE setVisible)

public:

    Q_INVOKABLE void setXpos(const int xpos);
    Q_INVOKABLE void setYpos(const int ypos);
    Q_INVOKABLE void setWidth(const int width);
    Q_INVOKABLE void setHeight(const int height);
    Q_INVOKABLE void setTextEn(const QString textEn);
    Q_INVOKABLE void setTextZh(const QString textZh);
    Q_INVOKABLE void setNormalPicPath(const QString normalPicpath);
    Q_INVOKABLE void setText(const QString text);
    Q_INVOKABLE void setVisible(bool visible);


    Q_INVOKABLE int xpos(void) const;
    Q_INVOKABLE int ypos(void) const;
    Q_INVOKABLE int width(void) const;
    Q_INVOKABLE int height(void) const;
    Q_INVOKABLE QString getTextEn(void) const;
    Q_INVOKABLE QString getTextZh(void) const;
    Q_INVOKABLE QString getNormalPicPath(void) const;
    Q_INVOKABLE QString getText(void) const;
    Q_INVOKABLE bool isVisible(void) const;

public:
    explicit weatherWindow(QObject *parent = 0);
    bool updateWeather();
signals:
    void appItemClicked(int);
    void sendMsgToQml(QVariant msg, QVariant wParam, QVariant lParam);
    void sendLoaderEvent();
public slots:
    Q_INVOKABLE void timezoneClicked();
    Q_INVOKABLE void weatherzoneClicked(int);


private:
    int m_xpos;
    int m_ypos;
    int m_width;
    int m_height;
    QString m_textEn;
    QString m_textZh;
    QString m_textTw;
    QString m_normalPicPath;
    QString m_text;
    QObject *m_rootObject;
    bool m_visible;
};

#endif // WEATHERWINDOW_H

weatherwindow.cpp

#include "weatherwindow.h"
#include <QDir>
#include <QChar>
#include <QQmlProperty>
#include <QQmlComponent>
#include <QQmlEngine>
#include <sstream>
#include <QTime>



#define DECIMAL_CODE                 10
#define NOON_TIME_BASE               12
#define MAX_WEEK_DAYS                7
#define STRING_TEMP_LOW_TEMPERATURE  17
#define STRING_TEMP_HIGH_TEMPERATURE 25

#define STRING_CITY_NAME_EN     "guangzhou"
#define STRING_CITY_NAME_CHN    "广州"
#define STRING_WEATHER_EN       "Cloudy"
#define STRING_WEATHER_CHN      "多云"
#define STRING_TEMPERATURE_EN   "Temp"
#define STRING_TEMPERATURE_CHN  "温度"
#define STRING_RANGE_TO         "~"
#define STRING_COLON_EN         ":"
#define STRING_COLON_CHN        ":"
#define STRING_CELSIUS          "26℃"

#define STRING_AM               "AM"
#define STRING_PM               "PM"
#define STRING_NULL             ""

#define STRING_ROOT             "/"

#define ID_LANGUAGE             11
#define ID_TIMEFORMAT           12
#define ID_WEATHER              13

weatherWindow::weatherWindow(QObject *parent) : QObject(parent)
{
    setXpos(200);
    setYpos(300);
    setWidth(360);
    setHeight(500);
    setTextEn("weatherWindow");
}

bool weatherWindow::updateWeather()
{
    emit sendMsgToQml(ID_WEATHER, WEATHER_CITY, STRING_CITY_NAME_CHN);
    qDebug("weatherWindow::emit sendMsgToQml(ID_WEATHER, WEATHER_CITY\r\n");

    emit sendMsgToQml(ID_WEATHER, WEATHER_WEATHER,STRING_WEATHER_CHN);
    qDebug("weatherWindow::emit sendMsgToQml(ID_WEATHER, WEATHER_WEATHER\r\n");

    emit sendMsgToQml(ID_WEATHER, WEATHER_TEMP, STRING_CELSIUS);
    qDebug( "weatherWindow::emit sendMsgToQml(ID_WEATHER, WEATHER_TEMP)\r\n");

    return true;
}

void weatherWindow::setXpos(const int xpos)
{
    m_xpos = xpos;
}


void weatherWindow::setYpos(const int ypos)
{
    m_ypos = ypos;
}

void weatherWindow::setWidth(const int width)
{
    m_width = width;
}


void weatherWindow::setHeight(const int height)
{
    m_height = height;
}


void weatherWindow::setTextEn(const QString text)
{
    m_textEn = text;
}


void weatherWindow::setTextZh(const QString text)
{
    m_textZh = text;
}


void weatherWindow::setNormalPicPath(const QString path)
{
    m_normalPicPath = path;
}

void weatherWindow::setText(const QString text)
{
    m_text = text;
}


void weatherWindow::setVisible(bool visible)
{
    m_visible = visible;
}

//-----------------------------------READ---------------------------------------------
int weatherWindow::xpos(void)const
{
    return m_xpos;
}

int weatherWindow::ypos(void)const
{
    return m_ypos;
}


int weatherWindow::width(void)const
{
    return m_width;
}


int weatherWindow::height(void)const
{
    return m_height;
}


QString weatherWindow:: getTextEn(void)const
{
    return m_textEn;
}


QString weatherWindow:: getTextZh(void)const
{
    return m_textZh;
}


QString weatherWindow:: getNormalPicPath(void)const
{
    return m_normalPicPath;
}


QString weatherWindow:: getText(void)const
{
    return m_text;
}


bool weatherWindow:: isVisible(void) const
{
    return m_visible;
}

void weatherWindow::timezoneClicked()
{
    qDebug( "timezoneClicked !\n");

}
void weatherWindow::weatherzoneClicked(int Index)
{
    qDebug( "this func is for test only, Index = %d", Index);
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "weatherwindow.h"


#define STRING_WND       "weatherwindow"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    weatherWindow *weatherWdn = new weatherWindow;
    QQmlApplicationEngine engine;


    QQmlContext *context = engine.rootContext();
    if (context == NULL) {
        qDebug( "QQmlContext is NULL \r\n");
        return false;
    }
    context->setContextProperty(STRING_WND, weatherWdn);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    weatherWdn->updateWeather();

    QObject* root = engine.rootObjects().first();
    QObject* pctrlobj = root->findChild<QObject*>("pageProgress");
    if(pctrlobj)
    {
        qDebug("home ui get  pctrlobj!!!");
        QVariant msg="home ui get  pctrlobj";

        QMetaObject::invokeMethod(pctrlobj,"hideRear",Q_ARG(QVariant,msg));
    }

    return app.exec();
}

Weather.qml

import QtQuick 2.0

Item {
    id:weatherPage
    objectName: "firstPageName"
    width: 1024
    height: 360
    property bool dotshow: true
    property int first_page_language:   11
    property int first_page_timeformat: 12
    property int first_page_weather:    13

    property int first_page_language_id: 1

    property int time_format_12H:                   0
    property int time_format_24H:                   1
    property int cur_time_format:                   time_format_24H

    property int weather_city:                      0
    property int weather_weather:                   1
    property int weather_temp:                      2
/*    function mytestFirstPage()  base qml can call child func
    {
        console.log("++++++++++++++++++++++++cks++++++++++++++++just for test ");
    }*/

    //export this two function to the other qml
    function timezoneClicked()
    {
        weatherwindow.timezoneClicked();
    }

    function weatherzoneClicked()
    {
        weatherwindow.weatherzoneClicked(2);
    }

    Connections {
        target: weatherwindow
        onSendMsgToQml: {
            switch (msg) {
                case first_page_language:
                    first_page_language_id=wParam;
                    console.log("update language:"+wParam);
                    break;
                case first_page_timeformat:
                    console.log("update timeformat:"+wParam);
                    switch(wParam)
                    {
                    case time_format_12H:
                        cur_time_format = time_format_12H;
                        break;
                    case time_format_24H:
                        cur_time_format = time_format_24H;
                        break;
                    default:
                        break;
                    }
                    updatelocaltime();
                    break;
                case first_page_weather:
                    console.log("update weather:"+wParam);
                    switch(wParam)
                    {
                    case weather_city:
                        console.log("update weather:city"+lParam);
                        textCity.text = lParam;
                        break;
                    case weather_weather:
                        console.log("update weather:weather"+lParam);
                        textWeather.text = lParam;
                        break;
                    case weather_temp:
                        console.log("update weather:temp"+lParam);
                        textTemp.text = lParam;
                        break;
                    }
                    break;
                default:
                    break;
            }
        }
    }

    function getWeekDay(curWeekDay)
    {
        var strCurWeekDay;
        if(first_page_language_id == 0)
        {
                if (curWeekDay == 1) {
                    strCurWeekDay =  "MON";
                }
                else if (curWeekDay == 2) {
                    strCurWeekDay = "TUE";
                }
                else if (curWeekDay == 3) {
                    strCurWeekDay =  "WED";
                }
                else if (curWeekDay == 4) {
                    strCurWeekDay =  "THU";
                }
                else if (curWeekDay == 5) {
                    strCurWeekDay =  "FRI";
                }
                else if (curWeekDay == 6) {
                    strCurWeekDay =  "SAT";
                }
                else if (curWeekDay == 7) {
                    strCurWeekDay =  "SUN";
                }
        }
        else if(first_page_language_id == 1)
        {
                if (curWeekDay == 1) {
                    strCurWeekDay =  "\u661f\u671f\u4e00";
                }
                else if (curWeekDay == 2) {
                    strCurWeekDay =  "\u661f\u671f\u4e8c";
                }
                else if (curWeekDay == 3) {
                    strCurWeekDay =  "\u661f\u671f\u4e09";
                }
                else if (curWeekDay == 4) {
                    strCurWeekDay =  "\u661f\u671f\u56db";
                }
                else if (curWeekDay == 5) {
                    strCurWeekDay =  "\u661f\u671f\u4e94";
                }
                else if (curWeekDay == 6) {
                    strCurWeekDay =  "\u661f\u671f\u516d";
                }
                else if (curWeekDay == 7) {
                    strCurWeekDay =  "\u661f\u671f\u65e5";
                }
        }
        else if(first_page_language_id == 2)
        {
                if (curWeekDay == 1) {
                    strCurWeekDay =  "\u661f\u671f\u4e00";
                }
                else if (curWeekDay == 2) {
                    strCurWeekDay =  "\u661f\u671f\u4e8c";
                }
                else if (curWeekDay == 3) {
                    strCurWeekDay =  "\u661f\u671f\u4e09";
                }
                else if (curWeekDay == 4) {
                    strCurWeekDay =  "\u661f\u671f\u56db";
                }
                else if (curWeekDay == 5) {
                    strCurWeekDay =  "\u661f\u671f\u4e94";
                }
                else if (curWeekDay == 6) {
                    strCurWeekDay =  "\u661f\u671f\u516d";
                }
                else if (curWeekDay == 7) {
                    strCurWeekDay =  "\u661f\u671f\u65e5";
                }
        }
        return strCurWeekDay;
    }


        function updatelocaltime()
    {
        var d = new Date();
        var tempHour = d.getHours();
        var tempMin = d.getMinutes();
        var curWeekDay = d.getDay();
        var curYears = d.getFullYear();
        var curMonths = d.getMonth()+1;
        var curDay = d.getDate();

        var hour1=0;
        var hour2=0;
        var min1=0;
        var min2=0;
        var curTime;
        var textDay = "";

        if (cur_time_format == time_format_12H) {
            if(tempHour > 12)
            {
                tempHour -= 12;
                textAMPM.text = "PM";
                if(first_page_language_id == 1 || first_page_language_id == 2)
                {
                    textAMPM.text = "\u4e0b\u5348";
                }
            } else {
                textAMPM.text = "AM";
                if(first_page_language_id == 1 || first_page_language_id == 2)
                {
                    textAMPM.text = "\u4e0a\u5348";
                }
            }
        } else {
            textAMPM.text = "";
        }
        hour1 = parseInt(tempHour / 10);
        hour2 = tempHour % 10;
        min1 = parseInt(tempMin / 10);
        min2 = tempMin % 10;
        hourH.source = getPngName(hour1);
            hourL.source = getPngName(hour2);
          dotdot.source="Res/clockSlider.png"
            minH.source = getPngName(min1);
            minL.source = getPngName(min2);
    if(dotshow)
    {
        dotshow = false;
        dotdot.visible = false;
    }
    else
    {
        dotshow = true;
        dotdot.visible = true;
    }
    if(curWeekDay > 0 && curWeekDay <= 7) {
                textDay = getWeekDay(curWeekDay) +"\n" + curYears + "-" + curMonths + "-" +curDay;
                textCurDay.text = textDay;
            }
    }

    Timer{
        interval: 1000;
        repeat: true
        running: true;
        triggeredOnStart: true
        onTriggered: {
            updatelocaltime();
        }
    }

    function getPngName(x)
    {
        return ("Res/"+x+".png");
    }
    Rectangle{
        color: "white"
        x: 80
        y: 40
        width: 800
        height: 130
        opacity: 0.5
        radius: 30
        MouseArea{
            anchors.fill: parent
            onClicked: {
                console.log("weatherwindow x :"+weatherwindow.xpos)
                console.log("weatherwindow y :"+weatherwindow.ypos)
                console.log("weatherwindow w :"+weatherwindow.width)
                console.log("weatherwindow h :"+weatherwindow.height)
                console.log("weatherwindow textEn :"+weatherwindow.textEn)
                console.log("weatherwindow getTextEn() :"+weatherwindow.getTextEn())
            }
        }
    }
    Rectangle {
        id: rectangleTimeWeather
        color: "#00ffffff"

        Image {
            id: hourH
            x: 115
            y: 65
            width: 35
            height: 70
        }
        Image {
            id: hourL
            x: 151
            y: 65
            width: 35
            height: 70
        }
        Image {
            id: dotdot
            x: 187
            y: 65
            width: 35
            height: 70
        }
        Image {
            id: minH
            x: 208
            y: 65
            width: 35
            height: 70
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
        }
        Image {
            id: minL
            x: 247
            y: 65
            width: 35
            height: 70
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
        }

        Text {
            id: textAMPM
            x: 293
            y: 65
            width: 50
            height: 30
            color: "white"
            horizontalAlignment: Text.AlignLeft
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 20
        }

        Text {
            id: textCurDay
            x: 338
            y: 55
            width: 154
            height: 100
            color: "white"
            horizontalAlignment: Text.AlignLeft
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 24
        }
        Image {
            id: borderImage1
            x: 588
            y: 40
            width: 135
            height: 130
            source: "Res/weather_cloudy.png"
        }

        Text {
            id: textCity
            x: 730
            y: 50
            width: 184
            height: 40
            color: "#ffffff"
            horizontalAlignment: Text.AlignLeft
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: 30
        }

        Text {
            id: textWeather
            x: 733
            y: 93
            width: 180
            height: 35
            color: "#ffffff"
            horizontalAlignment: Text.AlignLeft
            font.pixelSize: 24
        }
        Text {
            id: textTemp
            x: 733
            y: 128
            width: 180
            height: 35
            color: "#ffffff"
            horizontalAlignment: Text.AlignLeft
            font.pixelSize: 24
        }
    }
}

main.qml

import QtQuick 2.0
import QtQuick.Window 2.2

Window {
    visible: true
    width:1000
    height:520
    Image {
        id: background
        anchors.fill: parent
        source: "Res/background.png"
    }
    Weather{
        x: 0
        y: 100
        //visible: view.currentIndex == 1 ? false:true
        opacity: 1
    }
    Item {
       id: test
       objectName: "pageProgress"
       function hideRear(msg)
       {
           console.log("hideRear $$$$$$$$$$$$$$ "+msg)
           return "some return"
       }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值