做跨境电商有没推荐的网站,江门网站建设报价,网站开发主要职责,中国黄金集团建设有限公司官方网站QML与C交互 QML中调用C功能、使用QML或者Quick中的C接口、使用C实现自定义的QML对象 注#xff1a; 只有QObject的派生类才能与QML交互 QML引擎集成Qt元对象系统#xff0c;QObject的派生子类的属性、方法、信号都可以在QML中访问 C类可以被注册为一个QML实例 C类可以被注册为… QML与C交互 QML中调用C功能、使用QML或者Quick中的C接口、使用C实现自定义的QML对象 注 只有QObject的派生类才能与QML交互 QML引擎集成Qt元对象系统QObject的派生子类的属性、方法、信号都可以在QML中访问 C类可以被注册为一个QML实例 C类可以被注册为一个单例类型可在QML中导入单例对象 C类实例可以作为上下文属性或上下文对象嵌入到QML中 1.QML运行时C类 Qt QML模块实现了QML框架的C类客户端可以使用这些类与QML运行时进行交互 以C为切入点的QML客户端启动时会 1.客户端初始化一个QQmlEngine 2.使用QQmlComponent对象加载QML文件 3.QML引擎提供一个默认的QQmlContext对象作为顶层执行上下文用来执行QML文件中定义的函数、表达式通过QQmlEngine::rootContext获取该上下文 4.若加载QML文件没错时QML文件的对象将使用QQmlComponent对象的create()创建。 5.所有对象创建完毕客户端将控制权交给应用程序的事件循环 2.QQmlEngine 2.1提供一个QML引擎管理qml文件的对象层次结构 2.2提供一个默认上下文即根上下文代表执行环境保证在需要时对象属性可以被更新 2.3允许将全局设置应用到它管理的所有对象
3.QQmlApplicationEngine 是 QQmlEngine的子类结合了QQmlEngine、QQmlComponent功能 更简便的实现从一个单一的qml文件加载应用程序 提供一些核心应用程序功能一般由C控制 例如 QQmlQpplicationEngine engine; engine.load(QStringLiteral(“qrc:/main.qml”)) 一般QQmlQpplicationEngine加载的qml文件其根对象应该是widnow或者ApplicationWindow不然无法显示 若要加载根不是window或其子类的qml文件时使用 QQuickView* viewnew QQuickView view-setSource(QUrl::fromLocalFile(“myqmlfile.qml”)) view-show() 4.QQmlContext 提供了对象实例化和表达式执行所需的上下文 所有对象都要在特定的上下文中实例化 QQmlContext在QML引擎中定义了一个上下文允许将数据暴露给由QML引擎实例化的QML组件 QQmlContext属性能通过名字将数据显示绑定到上下文使用setContextProperty() 例如 QQmlEngine engine; QStingListModel modelData; QQmlContext* context engine.rootContext() context-setContextProperty(“stringModel”,modelData) QQmlContext创建者需要有权去销毁QQmlContext对象 下方例子中context由根上下文中创建了一个新的上下文modelData被添加到该新的的上下文 window销毁后新创建的context必须显示销毁可以将window作为context父对象利用QT的对象内存结构自动销毁 例如 QQmlEngine engine; QStingListModel modelData; QQmlContext* context new QQmlContext(engine.rootContext()) ; context-setContextProperty(“stringModel”,modelData) //和下面代码的区别 QQmlComponent component(engin); component.setData(“importQtQuick;ListView{model:stringModel}”,QUrl()); QObject* windowcomponent.create(); 在QQmlContext中设置一上下文(按照这样new QQmlContext(engine.rootContext()))上下文对象的是所有属性都可以在context中通过名称访问 使用上下文对象可以更简单快捷维护属性 例如 class MyDataSet:public QObject { Q_PROPERTY(QAbstractItemModel* myModel READ NOTIFY modelChanged) }; MyDataSet myDataSet; QQmlEngine engine; QQmlContext* contextnew QQmlContext(engine.rootContext()); context-setContextObject(myDataSet); //和上面代码的区别 QQmlComponent componet(engine); componet.setData(“import QtQuick;ListView{model:myModel}”,QUrl()); component.create(context); 使用setContextProperty显示设置的属性优先于上下文对象的属性 QQmlEngine engine; QQmlContext* context1new QQmlContext(engine.rootContext()); QQmlContext* context2new QQmlContext(context1); //context2 是context1的子上下文。 context1-setContextProperty(“a”,12); context1-setContextProperty(“b”,15); context2-setContextProperty(“5”,15); //context2具有context1的全部属性 5.QQmlComponent 动态对象实例化 可以使用C直接创建也可以通过createComponent在QML中创建 组件是可重用的、具有定义好的对外接口的封装QML类型 QQmlComponent封装了QML组件的定义用于加载QML文档需要QQmlComponent实例化QML的对象 例如 qml import QtQuick Item{width:100;height:100} c #include #include #include int main(int argc,char* argv[]) { QCoreApplication a(argc,argv); QQmlEngine engine; QQmlComponent component(engine,Qurl::fromLocalFile(“…/main.qml”)); QObject* myObjcomponent.create(); QuickItem* item qobject_castQQuickItem*(myObj); qreal width item-width(); return a.exec(); } 如果QQmlComponent要加载网络中的QML文件时需要先获取到文件才能加载所以有一个过程会变成Loading只有状态变为Ready后才能调用create void Init(){ QQmlComponent component(engine,Qurl(“http://www.eample.com/main.qml”)); if(component-isLoading()) { QObject::connect(component,QQmlComponent::statusChanged,this,MyApplication::continuedLoading) } else { continuedLoading(); } } void continuedLoading() { if(component-isError()) { qWarning component-errors(); }else { QObject* myObj component-create(); } } 6.QQmlExpression 动态执行表达式 允许客户端在C中利用一个特定的上下文执行javascript表达式表达式的结果以QVariant返回 例子 xx.qml文件 Item{ width100;height:100 } C中 QQmlEngine engine new QQmlEngine(); QQmlComponent component(engine,QUrl::fromLocalFile(“xx.qml”)); QObject* objectcomponent.create(); QQmlExpression* express new QQmlExpression(engine-rootContext(),object,“width*2”); int ret expression-evaluate().toInt(); 7.QML中注册C类型 7.1 qmlRegisterType Qt5.14后不在推荐使用qmlRegisterType 7.2 基于宏的注册方式 Qt5.15后使用一组可以添加到类定义中的宏注册C会将类型导出到QML中 QML_ELEMENT: 最重要的宏 可以将所在的类提供给QML作为类型类型名称就是类名 QML_NAMED_ELEMENT(name)可以自定义类型名 例子 c文件 #include QtQml/qqmlregistration.h //必备 class Backend:public QObject { Q_OBJECT Q_PROPERTY(QString username READ userName WRITE setUserName NOTIFY usernameChanged) QML_ELEMENT //必备 public: explicit Backend(QObject* parent nullptr){} QString username(){return m_userName;} void setUserName(const QString userName) { m_userName userName; emit userNameChanged(); } signals: void userNameChanged(); private: QString m_userName; }; 在pro文件中添加如下 CONFIG qmltypes QML_IMPORT_NAMEio.qt.examples.backend QML_IMPORT_MAJOR_VERSION 1 这样就可以在类型命名控件为《io.qt.examples.backend》中注册版本为1的类型 次要版本将从附加到属性、方法、信号的任何修订中派生默认次要版本为0 将QML_ADDED_IN_minor_VERSION()宏添加到类定义中可以显示的将类型限制为特定的次要版中可用 在qml文件中 import QtQuick import QtQuick.Controls import io.qt.examples.backend //C中的类型空间 ApplicationWindow{ id:root width:100;height:100 visible:true BackEnd{ id:backend onUserNameChanged:console.log(backend.userName); } Column{ spacing:10 anchors.centerIn:parent TextField{ placeholderText:qsTr(“User Name”) onTextChanged:backend.username text } Label{ text:backend.username width:100;height:100 background:Rectangle{ color:“lightgrey” } } } } 7.3 注册值类型 具有Q_GADGET宏的任何类型都可以注册为QML值类型 Q_GADGET是Q_OBJECT简化版适用于不从QOBJECT派生但希望使用QMetaObject的一些功能 可以使用Q_ENUM、Q_PROPERTY、Q_INVOKABLE但不能使用信号和槽 值类型名称需要小写 注册方式QML_VALUE_TYPE或者QML_ANONYMOUS class Person{ Q_GADGET Q_PROPERTY(QString firstName READ firstName WRITE setFirstName NOTIFY fierstNameChanged) Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY usernameChanged) QML_VALUE_TYPE(persion) //值类型名称需要小写 } 使用方式和7.2类似 7.4注册不可实例的对象类型 有时候需要将QObject派生类注册为不可实例化的对象类型 符合情况的C类 - 该类是个接口类型不应该被实例化 - 该类不需要向QML公开的基类 - 仅声明一些可以从QML访问的枚举 - 是应通过单例提供给QML的类型 QML提供了以下几种方法用于注册非实例化的类型的宏 QML_ANONYMOUS: 注册不可实例化且无法从QML引用的C类型 QML_INTERFACE注册Qt接口类型 QML_UNCREATETABLE(reason)注册一个命名的C类型不可实例但可被QML系统识别需要搭配QML_ELEMENT或者QML_NAMED_ELEMENT QML_SINGLETON注册一个可以从QML导入的单例类型需要搭配QML_ELEMENT或者QML_NAMED_ELEMENT 单例允许QML使用命名空间访问其属性值、信号、函数不需要手动实例化一个对象 单例类型不需要和QQmlContext关联它被所有上下文共享 单例类型由QQmlEngine构造持有engine销毁该单例销毁 8. 定义QML特定类型、属性 8.1 附加属性 QML中有一个附加属性、附加信号处理器是附加到一个对象的额外特性 8.2属性修饰符类型 可以作用于QML对象实例的一种属性 属性值设置拦截器在属性被设置时用于过滤和改变设置值 属性值源随时间推移自动更新值 8.3指定QML对象为默认属性、父级属性 Q_CLASSINFO宏和DefaultProperty搭配指定默认属性 class A{ Q_CLASSINFO(“DefaultProperty”,“messages”) //将属性messages设置为默认属性 Q_CLASSINFO(“ParentProperty”,“boadr”) //告诉QML哪个属性表示QML层次结构父对象 } 8.4枚举类型 使用自定义枚举类型需要先将类注册枚举使用Q_ENUM()声明 class Message:public QObject { Q_OBJECT Q_PROPERTY(Status staus READ status NOTIFY statusChanged) public: enum Status{ready,Loading,Error}; Q_ENUM(Status) Status status( )const; signals: void statusChanged(); } 在qml文件中使用 Message { onStatusChanged: { if(status Message.Ready) { console.log(“Message is loaded”) } } } 9.使用C属性 QObject的子类或者包含有Q_GADGET宏的类的所有属性都能够被QML访问 可以使用Q_PROPERTY宏定义属性 例子 class Message:public QObject { Q_OBJECT Q_PROPERTY(Status staus READ status NOTIFY statusChanged) Q_PROPERTY(QString m_author READ author WRITE setAuthor NOTIFY authorChanged) public: enum Status{ready,Loading,Error}; Q_ENUM(Status) Status status( )const; QString authorconst{return m_author;} void SetAuthor(const QString autho) { if(autho ! m_author) { m_authorautho; emit authorChanged(); } } signals: void statusChanged(); void authorChanged(); private: QString m_author; } cpp文件中 QQuickView view; Message msg; view.engine()-rootContext()-setContextProperty(“msg”,msg); view.setSource(QUrl::fromLocalFile(MyItem.qml)); view.show(); 在qml文件中 import QtQuick Text { width:100;height:100; text:msg.author //调用author() Component.onCompleted: { msg.author “Jonah” //调用SetAuthor() } } 10.增强QML、C交互性属性都应该显示关联一个NOTIFY属性属性改变时发射该信号 10.1 对象类型属性 如果类注册到QML在qml中可以直接使用这个类 class Message : public QObject { Q_OBJECT Q_PROPERTY(QString m_author READ author WRITE setAuthor NOTIFY authorChanged) public: QString authorconst{return m_author;} void SetAuthor(const QString autho) { if(autho ! m_author) { m_authorautho; emit authorChanged(); } } signals: void authorChanged(); private: QString m_author; } 在qml中直接 Message{} 10.2对象列表属性 如果属性包含QObject子类列表在QML中访问必须使用QQmlListProperty作为属性类型 class MessageBoadr: public QObject { Q_OBJECT Q_PROPERTY(QQmlListProperty messages READ messages) public: QQmlListProperty messages()const; //返回一个由QListMessage* m_messages构造的新的QQmlListProperty对象 { return QQmlListProperty(this,0,MessageBoard::append_message); } private: static void append_message(QQmlListProperty* list,Message* msg) { MessageBoard* msgBoardqobject_castMessageBoard*(list-object); if(msg) msgBoard-m_messages.append(msg); } QListMessage* m_messages; } 10.3属性组 属性组用于描述一个类型相关的特征 class MessageAuthor:publicQObject { Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(QString email READ email WRITE setEmail) } class Message:public QObject { Q_OBJECT Q_PROPERTY(MessageAuthor* author READ author) public: Message(QObject* parent):QObject(parent),m_author(new MessageAuthor(this)){} MessageAuthor* author()const{return m_author;} private: MessageAuthor* m_author; } Message、MessageAuthor注册到QML后 Message { author.name:“aaa” author.email:“aaaqq.com” } 10.4使用函数和槽、信号 QML中可以有条件的访问QObject子类的函数 使用Q_INVOKABLE标记的public函数 public的槽函数 class MessageBoard:public QObject { Q_OBJECT public: Q_INVOKABLE bool postMessage(const QString msg) { return true; } signals: void newMessagePosted(const QString subject); public slots: void refresh(){} } cpp MessageBoard msgBoard QQuickView view; view.engine()-rootContext()-setContextProperty(“msgBoard”,msgBoard); view-setSource(QUrl::fromLocateFile(“MyItem.qml”)); view.show(); qml import QtQuick Item { width:100;height:100; MouseArea { anchors.fill:parent onClicked: { var result msgBoard.postMessage(“sss”); msgBoard.refresh(); } } onNewMwssagePosted:(subject){} } 10.5 C中使用QML QML可以使用QQmlComponent、QQuickView进行加载 – QQmlComponent读取到qml后将其转为c对象即可在C中进行修改 – QQuickView也和QQmlComponent类似不过由于QQuickView是QWindow的子类所以被加载的对象还可以进行可视化渲染 因此QQuickView用于将一个可视化的QML与应用程序的图形界面整合 Item { width:100 height:100 } 使用QQmlComponent QQmlEngine engine; QQmlComponent component(engine,QUrl::fromLocalFile(“main.qml”)); QObject* objcomponent.create(); //… delete obj; 获取到QObject后利用setPorperty、QQmlProperty对其属性修改 obj-setProperty(“width”,500); QQmlProperty(obj,“width”).write(600) 还可以转换成其他类型 QQuickItem* itemqobject_castQQuickItem*(object); item-setWidth(500); qDebug()property(“width”) 使用QQuickView QQuickView view; view.setSource(QUrl::fromLocalFile(“main.qml”)); view.show(); QQuickItem* itemview.rootObject(); item-setWidth(500); qDebug()width(); 10.6 连接QML信号 Item { id:item signal qmlSignal(msg:string) signal qmlSSignal(obj:Item) MouseArea { anchors.fill:parent onClicked: { item.qmlSignal(“sss”) item.qmlSSignal(item) } } } class MyClass:public QObject { Q_OBJECT public slots: void cppSlot(QString msg){} void cppSlot(QQuickItem* item){} } main: QQuickView view(QUrl:;fromLocalFile(“MyItem.qml”)); QObject* itemview.rootObject(); MyClass myClass; QObject::connect(item,SIGNAL(qmlSignal(QString)),myClass,SLOT(cppSlot(QSting))); QObject::connect(item,SIGNAL(qmlSignal(QVariant)),myClass,SLOT(cppSlot(QVariant))); view.show();