本文的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"
}
}
}