QML和C++混合编程
推荐博客:
http://blog.csdn.net/foruok/article/details/32698603
http://blog.csdn.net/zzti_erlie/article/details/53008987
https://blog.csdn.net/qq_33154343/article/details/79364846
编译环境: win10专业版 Qt Creator 4.5.2 based on Qt 5.9.5
工程创建步骤:New Project–>Application–>Qt Quick Application-Empty
工程名称:qml_mixed_Cpp
qml_mixed_Cpp.pro
QT += quick
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += main.cpp \
colormaker.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
colormaker.h
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "colormaker.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
/*
* 注册一个非单例QML类型, 然后就可以在QML里面调用了.
* qmlRegisterType()的第一个参数uri,指定唯一的包名
* 一是可以避免名字冲突,二是可以把多个相关类聚合到一个包中方便引用
* 比如我们常写的这句“import QtQuick.Controls 1.1”, 其中的“QtQuick.Controls”就是包名uri,“1.1”是版本(versionMajor和versionMinor的组合)
* qmlName则是QML中可以使用的类名
*/
qmlRegisterType<ColorMaker>("an.qt.ColorMaker",1,0,"ColorMaker");//包名:an.qt.ColorMaker,版本:1.0 类名:ColorMaker
//上面代码将ColorMaker类注册为QML类ColorMaker,主版本1,次版本0,
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
colormaker.h
#ifndef COLORMAKER_H
#define COLORMAKER_H
#include <QObject>
#include <QColor>
#include <QTimerEvent>
//实现可以导出的C++类
class ColorMaker : public QObject
{
Q_OBJECT
//导出的类定义了想在QML文件中使用的枚举类型,使用Q_ENUMS宏将该枚举类型注册到元对象系统中
Q_ENUMS(GenerateAlgorithm)
//Q_PROPERTY宏用来定义可通过元对象系统访问的属性,通过它定义的属性,可以在QML文件中访问、修改,也可以在属性变化时发射特定的信号
//注意:使用Q_PROPERTY宏,该类必须是QObject的后裔,必须先在类首使用Q_OBJECT宏
//Q_PROPERTY(type name READ name WRITE setName NOTIFY nameChanged)
/*
READ--声明一个读取属性的函数,该函数一般没有参数,返回定义的属性
WRITE---可选配置。声明一个设定属性的函数,它指定的函数没有返回值,只能有一个与属性类型匹配的参数。
NOTICE---可选配置。给属性关联一个信号(该信号必须是已经在类中声明过的),当属性的值发生变化时就会触发该信号。信号的参数一般就是你定义的属性。
*/
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(QColor timeColor READ timeColor)
public:
explicit ColorMaker(QObject *parent = nullptr);
~ColorMaker();
//枚举变量--5种颜色算法
enum GenerateAlgorithm{
RandomRGB,
RandomRed,
RandomGreen,
RandomBlue,
LinearIncrease //线性渐变
};
/*
通过把类成员函数声明为const 以表明它们不修改类对象。 任何不会修改数据成员的函数都应该声明为const类型。
如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,
编译器将指出错误,这样做的好处是提高程序了的健壮性。
*/
QColor color() const;//常量成员函数---指明不可修改成员变量的值
void setColor(const QColor & color);
QColor timeColor() const;
//在定义一个类的成员函数时, 使用Q_INVOKABLE宏来修饰,就可以让该方法被元对象系统调用。这个宏必须放在返回类型前面
Q_INVOKABLE GenerateAlgorithm getAlgorithm() const; //返回类型为GenerateAlgorithm,这是一个算法函数
Q_INVOKABLE void setAlgorithm(GenerateAlgorithm algorithm);//设置使用那种颜色计算方法
signals:
void colorChanged(const QColor & color);//改变颜色的信号
void currentTimer(const QString &strTime);//当前时间的信号
public slots:
void start();
void stop();
protected:
void timerEvent(QTimerEvent *event);//时间事件
private:
GenerateAlgorithm m_algorithm;
QColor myColor;//现在的颜色
int m_nColorTimer;//定时器的ID
};
#endif // COLORMAKER_H
colormaker.cpp
#include "colormaker.h"
#include <QTimerEvent>
#include <QDateTime>
ColorMaker::ColorMaker(QObject *parent)
: QObject(parent)
,m_algorithm(RandomRGB) //初始化一个随机的颜色算法
,myColor(Qt::black) //初始化赋值为黑色
,m_nColorTimer(0)
{
qsrand(QDateTime::currentDateTime().toTime_t());
}
ColorMaker::~ColorMaker()
{
}
//调用该函数,确定设置颜色顺便会发射颜色改变的信号
QColor ColorMaker::color() const
{
return myColor;
}
void ColorMaker::setColor(const QColor &color)
{
myColor = color;
emit colorChanged(myColor);
}
QColor ColorMaker::timeColor() const
{
QTime time = QTime::currentTime();
int r = time.hour();
int g = time.minute()*2;
int b = time.second()*4;
return QColor::fromRgb(r,g,b);//颜色根据当前时间来生成
}
ColorMaker::GenerateAlgorithm ColorMaker::getAlgorithm() const
{
return m_algorithm;
}
void ColorMaker::setAlgorithm(GenerateAlgorithm algorithm)
{
m_algorithm = algorithm;//赋值给类成员
}
void ColorMaker::start()//开启定时器
{
if(m_nColorTimer == 0)
{
m_nColorTimer = startTimer(100);//使用一个周期为1000毫秒的定时器来产生颜色
}
}
void ColorMaker::stop(){
if(m_nColorTimer > 0)
{
killTimer(m_nColorTimer);//停止定时器的使用
m_nColorTimer = 0;
}
}
//timerEvent事件消息
void ColorMaker::timerEvent(QTimerEvent *event)
{
static unsigned char u8_cnt=0;
if(event->timerId() == m_nColorTimer)
{
switch (m_algorithm) {
case RandomRGB:
myColor.setRgb(qrand()%255, qrand()%255, qrand()%255);
break;
case RandomRed:
//myColor.setRed(qrand()%255);
myColor.setRed(u8_cnt); u8_cnt>254?u8_cnt=0:u8_cnt+=10;
break;
case RandomGreen:
myColor.setGreen(u8_cnt); u8_cnt>254?u8_cnt=0:u8_cnt+=10;
break;
case RandomBlue:
myColor.setBlue(u8_cnt);u8_cnt>254?u8_cnt=0:u8_cnt+=10;
break;
case LinearIncrease:
{
int r = myColor.red() + 10;
int g = myColor.green() + 10;
int b = myColor.blue() + 10;
myColor.setRgb(r%255,g%255,b%255);
}
break;
default:
break;
}
//定时器触发时根据算法计算新的颜色值,发射colorChanged信号,同时也发送一个currentTime信号
emit colorChanged(myColor);
emit currentTimer(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
}
else
{
QObject::timerEvent(event);
}
}
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0 //控制版本
import QtQuick.Layouts 1.0 //布局版本
import an.qt.ColorMaker 1.0 //导入自定义的C++类
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("qml与C++混合编程-20200612")
Rectangle{
width: 360;
height: 360;
//显示时间文本的label
Text{
id:timeLabel;
anchors.left: parent.left;
anchors.leftMargin: 4;
anchors.top:parent.top;
anchors.topMargin: 4;
font.pixelSize: 26;
}
//这里调用了C++类,创建了一个供QML使用的C++对象
ColorMaker{
id:colorMaker;
color:Qt.green;
}
//中间显示颜色变化的矩形
Rectangle{
id:colorRect;
anchors.centerIn: parent;
width: 200;
height: 200;
color: "blue";
Text{
id:str_color_algorithm;
anchors.fill: colorRect;
anchors.centerIn: colorRect;
text:"sdasdasd";
}
}
//开始按钮
Button{
id:start;
text:"start";
anchors.left:parent.left;
anchors.leftMargin: 4;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 4;
onClicked: {
colorMaker.start();
}
}
//结束按钮
Button{
id:stop;
text:"stop";
anchors.left: start.right;
anchors.leftMargin: 4;
anchors.bottom: start.bottom;
onClicked: {
colorMaker.stop();
}
}
//改变颜色算法按钮
Button{
id:bt_colorAlgorithm;
text:"RGB";
anchors.left: stop.right;
anchors.leftMargin: 4;
anchors.bottom: start.bottom;
onClicked: {
var color_algorithm = (colorMaker.getAlgorithm()+1)%5;
changeAlgorithm(color_algorithm);
//str_color_algorithm.text = color_algorithm.toString();
colorMaker.setAlgorithm(color_algorithm);
}
function changeAlgorithm(algorithm){
switch(algorithm)
{
case 0:
str_color_algorithm.text = "RandomRGB";
break;
case 1:
str_color_algorithm.text = "RandomRed";
break;
case 2:
str_color_algorithm.text = "RandomGreen";
break;
case 3:
str_color_algorithm.text = "RandomBlue";
break;
case 4:
str_color_algorithm.text = "LinearIncrease";
break;
}
}
}
//JavaScript函数
//退出按钮
Button{
id:quit;
text:"quit";
anchors.left: bt_colorAlgorithm.right;
anchors.leftMargin: 4;
anchors.bottom: start.bottom;
onClicked: {
Qt.quit();
}
}
Component.onCompleted: {
colorMaker.color = Qt.rgba(0,180,120,255);
colorMaker.setAlgorithm(ColorMaker.LinearIncrease);
str_color_algorithm.text = "LinearIncrease";
}
//关联控件colorMaker和槽函数onCurrentTimer
Connections{
target: colorMaker; //接收事件的对象
onCurrentTimer:{ //接收事件时的处理函数
timeLabel.text = strTime; //strTime是currentTimer信号里的参数
timeLabel.color = colorMaker.timeColor;
}
}
Connections{
target: colorMaker;
onColorChanged:{
colorRect.color = color;
}
}
}
}