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;
}
}
}
}