本文共 12264 字,大约阅读时间需要 40 分钟。
QML其实是对ECMAScript的扩展,融合了Qt object系统,它是一种新的解释性语言,QML引擎虽然由Qt C++实现,但QML对象的运行环境说到底和C++对象的上下文环境是不通的,是平行的两个世界,如果想在QML中访问C++对象,那么必然要找到一种途径在两个运行环境之间建立沟通的桥梁。
Qt提供了两种在QML环境中使用C++对象的方式:
(1)在C++中实现一个类,注册为QML环境的一个类型,在QML环境中使用该类型创建对象
(2)在C++中构造一个对象,将这个对象设置为QML的上下文属性,在QML环境中直接使用该属性
要想将一个类或对象导出到QML中,必须满足以下几个条件:
(1)从QObject或QObject的派生类继承
(2)使用Q_OBJECT宏
(3)Q_INVOKABLE宏
在定义一个类的成员函数时使用Q_INVOKABLE宏来修饰,就可以让该方法被元对象系统调用,这个宏必须放在返回类型前面
(4)Q_ENUMS宏
如果要导出的类定义了想在QML中使用的枚举类型,可以使用Q_ENUM宏将该枚举注册到元对象系统中
(5)Q_PROPERTY宏
Q_PROPERTY宏用来定义可以通过元对象系统访问的属性,通过它定义的属性,可以在QML中访问,修改,也可以在属性变化时发射特定的信号
#ifndef COLORMAKER_H#define COLORMAKER_H#include#include class ColorMaker : public QObject{ Q_OBJECT Q_ENUMS(GenerateAlgorithm) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(QColor timeColor READ timeColor)public: explicit ColorMaker(QObject *parent = nullptr); ~ColorMaker(); enum GenerateAlgorithm { RandomRGB, RandomRed, RandomGreen, RandomBlue, LinearIcrease }; QColor color() const {return m_currentColor;} void setColor(const QColor& color); QColor timeColor() const; Q_INVOKABLE GenerateAlgorithm alorithm() const; Q_INVOKABLE void serAlgorithm(GenerateAlgorithm algorithm);signals: void colorChanged(const QColor& color); void currentTime(const QString& strTime);public slots: void start(); void stop();protected: void timerEvent(QTimerEvent *e);private: GenerateAlgorithm m_algorithm; QColor m_currentColor; int m_nColorTimer;};#endif // COLORMAKER_H
#include "colormaker.h"#include#include #include ColorMaker::ColorMaker(QObject *parent) : QObject(parent) ,m_algorithm(RandomRGB) ,m_currentColor(Qt::black) ,m_nColorTimer(0){ qsrand(QDateTime::currentDateTime().toTime_t());}ColorMaker::~ColorMaker(){}void ColorMaker::setColor(const QColor &color){ m_currentColor = color; emit colorChanged(color);}QColor ColorMaker::timeColor() const{ QTime time = QTime::currentTime(); qDebug() << time.toString("yyyy-MM-dd hh:mm:ss"); int r = time.hour(); int g = time.minute() * 2; int b = time.second() * 4; qDebug() << r << ":"<< g << ":"<< b; return QColor(r,g,b);}ColorMaker::GenerateAlgorithm ColorMaker::alorithm() const{ return m_algorithm;}void ColorMaker::serAlgorithm(ColorMaker::GenerateAlgorithm algorithm){ m_algorithm = algorithm;}void ColorMaker::start(){ qDebug() << "ColorMaker start"; if (m_nColorTimer == 0) { m_nColorTimer = startTimer(1000); }}void ColorMaker::stop(){ if (m_nColorTimer > 0) { killTimer(m_nColorTimer); m_nColorTimer = 0; }}void ColorMaker::timerEvent(QTimerEvent *e){ if (e->timerId() == m_nColorTimer) { switch (m_algorithm) { case RandomRGB: m_currentColor.setRgb(qrand()%255, qrand()%255,qrand()%255); break; case RandomRed: m_currentColor.setRed(qrand()%255); break; case RandomGreen: m_currentColor.setGreen(qrand()%255); break; case RandomBlue: m_currentColor.setBlue(qrand()%255); break; case LinearIcrease: { int r = m_currentColor.red() + 10; int g = m_currentColor.green() + 10; int b = m_currentColor.blue() + 10; m_currentColor.setRgb(r%255,g%255,b%255); } break; default: break; } emit colorChanged(m_currentColor); emit currentTime(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); } else { return QObject::timerEvent(e); }}
要注册一个QML类型,有多种方法:
qmlRegisterSingletonType()注册一个单例类型
qmlRegisterType()注册一个非单例类型
qmlRegisterTypeNotAvaliable()注册一个类型用来占位
qmlRegisterUncreatableType()通常用来注册一个具有附加属性的附加类型,具体参考Qt SDK
templateint qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName); template int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
uri 指定唯一的包名
qmlname 是QML中可以使用的类名
qmlRegisterType("an.qt.ColorMaker", 1, 0, "ColorMaker");
一旦你在C++中注册好了QML类型,就可以在QML文档中引入你注册的包,然后使用注册的类型了
import an.qt.ColorMaker 1.0
#include#include #include #include #include "colormaker.h"int main(int argc, char *argv[]){ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); //QQmlApplicationEngine engine; //engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); //if (engine.rootObjects().isEmpty()) // return -1; qmlRegisterType ("an.qt.ColorMaker", 1, 0, "ColorMaker"); QQuickView viewer; viewer.setResizeMode(QQuickView::SizeRootObjectToView); viewer.setSource(QUrl("qrc:///main.qml")); viewer.show(); return app.exec();}
引入包后,你可以在QML中创建 C++导入类型的对象了,与QML内建类型的使用完全一样。
Rectangle{ width: 360; height: 360; ColorMaker { id:colorMaker; color:Qt.green; }}
例:
import QtQuick 2.2import QtQuick.Window 2.2import QtQuick.Controls 1.4import QtQuick.Controls.Styles 1.4import QtQuick.Dialogs 1.3import QtQml 2.11import an.qt.ColorMaker 1.0Rectangle{ width: 360; height: 360; Text { id: timeLabel; anchors.left: parent.left; anchors.leftMargin: 4; anchors.top : parent.top; anchors.topMargin: 4; font.pixelSize: 26; } ColorMaker { id:colorMaker; color:Qt.green; } Rectangle { id:colorRect; anchors.centerIn: parent; width: 200; height: 200; color: "blue"; } Button { id:start; text:"start"; anchors.left: parent.left; anchors.leftMargin: 4; anchors.bottom: parent.bottom; anchors.bottomMargin: 4; onClicked: { console.log("start onClicked"); colorMaker.start(); } } Button { id:stop; text:"stop"; anchors.left: start.right; anchors.leftMargin: 4; anchors.bottom: start.bottom; anchors.bottomMargin: 4; onClicked: { colorMaker.stop(); } } function changeAlgorithm(button, algorithm) { switch(algorithm) { case 0: button.text = "RandomRGB" break; case 1: button.text ="RandomRed"; break; case 2: button.text ="RandomGreen"; break; case 3: button.text ="RandomBlue"; break; case 4: button.text ="LinearIncrease"; break; } } Button { id:colorAlgorithm; text:"RandomRGB"; anchors.left:stop.right; anchors.leftMargin: 4; anchors.bottom: stop.bottom; onClicked: { var algorithm = (colorMaker.alorithm() + 1 ) % 5; changeAlgorithm(colorAlgorithm,algorithm); colorMaker.serAlgorithm(algorithm); } } Button { id:quit text:"quit" anchors.left: colorAlgorithm.right; anchors.leftMargin: 4; anchors.bottom: colorAlgorithm.bottom; onClicked: { Qt.quit(); } } Component.onCompleted: { colorMaker.color = Qt.rgba(0,180,120,255); colorMaker.serAlgorithm(colorMaker.LinearIcrease); changeAlgorithm(colorAlgorithm,colorMaker.alorithm()); } Connections { target: colorMaker; onCurrentTime: { timeLabel.text = strTime; console.log("onCurrentTime"); // timeLabel.color = colorMaker.timeColor; } } Connections { target: colorMaker; onColorChanged: { colorRect.color = color; } }}/*Rectangle{ width: 600 height: 600 Image { id: imageLabel; width: 600; height: 540; anchors.top: parent.top anchors.left: parent.left fillMode: Image.PreserveAspectFit source: "http://images.cnblogs.com/cnblogs_com/xiaobingqianrui/1185116/o_Image%201.png" } Button { id:openBtn width: 100; height: 40; text: "Open"; anchors.top:imageLabel.bottom anchors.topMargin: 10; anchors.left: parent.left anchors.leftMargin: 10; onClicked:fileDialog.open(); } Label { id:pathLabel; text: "Hello world" font.pixelSize: 22 font.italic: true color: "steelblue" anchors.top:imageLabel.bottom anchors.topMargin: 10; anchors.left: openBtn.right anchors.leftMargin: 10 } FileDialog { id:fileDialog title: "please choose a file" nameFilters: ["Image Files (*.jpg *.png *.gif)"] onAccepted: { imageLabel.source=fileDialog.fileUrl; console.log(fileDialog.fileUrl); var imageFile = new String(fileDialog.fileUrl); pathLabel.text=imageFile.slice(8); } }}*/
viewer.rootContext()->setContextProperty("colorMaker", new ColorMaker);
一旦调用setContextProperty()导出了属性,就可以在QML中使用了,不需要import语句
import QtQuick 2.2import QtQuick.Window 2.2import QtQuick.Controls 1.4import QtQuick.Controls.Styles 1.4import QtQuick.Dialogs 1.3import QtQml 2.11//import an.qt.ColorMaker 1.0Rectangle{ width: 360; height: 360; Text { id: timeLabel; anchors.left: parent.left; anchors.leftMargin: 4; anchors.top : parent.top; anchors.topMargin: 4; font.pixelSize: 26; } /* ColorMaker { id:colorMaker; color:Qt.green; }*/ Rectangle { id:colorRect; anchors.centerIn: parent; width: 200; height: 200; color: "blue"; } Button { id:start; text:"start"; anchors.left: parent.left; anchors.leftMargin: 4; anchors.bottom: parent.bottom; anchors.bottomMargin: 4; onClicked: { console.log("start onClicked"); colorMaker.start(); } } Button { id:stop; text:"stop"; anchors.left: start.right; anchors.leftMargin: 4; anchors.bottom: start.bottom; anchors.bottomMargin: 4; onClicked: { colorMaker.stop(); } } function changeAlgorithm(button, algorithm) { switch(algorithm) { case 0: button.text = "RandomRGB" break; case 1: button.text ="RandomRed"; break; case 2: button.text ="RandomGreen"; break; case 3: button.text ="RandomBlue"; break; case 4: button.text ="LinearIncrease"; break; } } Button { id:colorAlgorithm; text:"RandomRGB"; anchors.left:stop.right; anchors.leftMargin: 4; anchors.bottom: stop.bottom; onClicked: { var algorithm = (colorMaker.alorithm() + 1 ) % 5; changeAlgorithm(colorAlgorithm,algorithm); colorMaker.serAlgorithm(algorithm); } } Button { id:quit text:"quit" anchors.left: colorAlgorithm.right; anchors.leftMargin: 4; anchors.bottom: colorAlgorithm.bottom; onClicked: { Qt.quit(); } } Component.onCompleted: { colorMaker.color = Qt.rgba(0,180,120,255); //colorMaker.serAlgorithm(colorMaker.LinearIcrease); colorMaker.serAlgorithm(2); changeAlgorithm(colorAlgorithm,colorMaker.alorithm()); } Connections { target: colorMaker; onCurrentTime: { timeLabel.text = strTime; console.log("onCurrentTime"); // timeLabel.color = colorMaker.timeColor; } } Connections { target: colorMaker; onColorChanged: { colorRect.color = color; } }}
转载地址:http://qdlws.baihongyu.com/