首页 > 编程知识 正文

头文件定义全局变量,多个C文件引用,c的五行属性

时间:2023-05-04 20:26:39 阅读:54948 作者:2525

使用c代码中定义的功能,可以轻松扩展QML。 由于QML引擎与Qt元对象系统紧密集成,因此所有由QObject派生类发布的功能都可以通过QML代码访问。 这允许直接从QML访问c数据和函数,通常几乎不需要修改。

QML引擎可以在元对象系统上反射QObject实例。 这意味着,任何QML代码都可以访问QObject派生类实例的以下成员:

属性方法(假定它们在public slotsQ_INVOKABLE中进行了标记)以及枚举在Q_ENUMS中声明

相反,数据类型处理和从所有权c传输到QML的数据必须是QML引擎支持的类型,还作为属性值、方法参数或返回值或信号参数值。

默认情况下,引擎支持许多Qt C类型,可以在从QML中使用时自动进行适当的转换。

1.1、暴露属性为Q_PROPERTY)宏,可以在任何QObject 派生类中指定属性。

例如,以下是具有作者属性的Message类: 如Q_PROPERTY宏调用中所指定,可以使用author ()方法读取此属性,并使用setAuthor ) )方法写入此属性。

注意:请勿使用typedef或using指定Q_PROPERTY类型。 因为moc会被混淆。 这可能会导致某些类型失败。

错误的使用方法:

using FooEnum=Foo:Enum; classbar : publicqobject { q _ objectq _ property (fooenumenumreadenumwritesetenumnotifyenumchanged ) }; 正确的使用方法:

classbar : publicqobject { q _ objectq _ property (foo :3360 enumenumreadenumwritesetenumnotifyenumchanged ) }; 暴露属性示例:

classmessage : publicqobject { q _ objectq _ property (qstringauthorreadauthorwritesetauthornotifyauthorchanged ) public : emit authorChanged (; } } QString author () const ) returnm_author; }signals: void authorChanged (; private: QString m_author; (; 如果从c加载名为MyItem.qml的文件并将此类实例设置为上下文属性:

intmain(intargc,char *argv[] ) qguiapplicationapp(argc,argv ); qquickview视图; 消息msg; view.engine(-rootcontext ) )-setcontextproperty )、msg ); view.set source (qurl :3360来自本地文件(my item.qml ); view.show (; 返回app.exec (; }然后,可以从MyItem.qml读取author属性。

//my item.qmlimportqtquick 2.0 text { width :100; 调用height :100 text : msg.author//message :3360 author ()以获取此值component.on completed : { msg.author=' jjor 调用http://www.Sina.com/http://www.Sina.com/http://www.Sina.com /,该信号在属性值发生更改时发出。 这使属性可以与属性绑定一起使用。 这是QML的基本特性,它通过在依赖性值更改时自动更新属性来强制执行属性之间的关系。 这意味着通知QML引擎更新与属性相关的绑定。

>上面示例中如果 author 属性可写但没有关联的 NOTIFY 信号,则文本值将使用 Message::author() 返回的初始值进行初始化,但不会随此属性的任何后续更改而更新。此外,任何从 QML 绑定到属性的尝试都会从引擎产生运行时警告。

建议将 NOTIFY 信号命名为 <property>Changed,其中 <property> 是属性的名称。QML 引擎生成的关联属性更改信号处理程序将始终采用 on<Property>Changed 形式,无论相关 C++ 信号的名称如何,因此建议信号名称遵循此约定以避免任何混淆。

1.2、使用通知信号的注意事项

开发人员应确保仅在属性值实际更改时才发出属性更改信号。此外,如果一个属性或一组属性不经常使用,则允许对多个属性使用相同的 NOTIFY 信号。这应该小心完成以确保性能不会受到影响。

NOTIFY 信号的存在确实会产生很小的开销。在某些情况下,属性的值是在对象构造时设置的,随后不会更改。在这些情况下,可以将 CONSTANT 属性而不是 NOTIFY 信号添加到属性声明中。

CONSTANT 属性应仅用于其值仅在类构造函数中设置和最终确定的属性。

Qt属性系统。

1.3、具有对象类型的属性

对象类型属性可从 QML 访问,前提是对象类型已正确注册到 QML 类型系统。

例如,Message 类型可能具有 MessageBody* 类型的 body 属性:

class Message : public QObject{ Q_OBJECT Q_PROPERTY(MessageBody* body READ body WRITE setBody NOTIFY bodyChanged)public: MessageBody* body() const; void setBody(MessageBody* body);};class MessageBody : public QObject{ Q_OBJECT Q_PROPERTY(QString text READ text WRITE text NOTIFY textChanged)// ...}

假设 Message 类型已在 QML 类型系统中注册,允许将其用作 QML 代码中的对象类型:

Message{ // ...}

如果 MessageBody 类型也注册到类型系统,则可以将 MessageBody 分配给 Message 的 body 属性:

Message { body: MessageBody { text: "Hello, world!" }} 1.4、具有对象列表类型的属性

包含 QObject 派生类型列表的属性也可以暴露给 QML。然而,应该使用 QQmlListProperty 而不是 QList<T> 作为属性类型。 这是因为 QList 不是 QObject 派生的类型,因此无法通过 Qt 元对象系统提供必要的 QML 属性特征,例如修改列表时的信号通知。

例如,下面的 MessageBoard 类有一个 QQmlListProperty 类型的消息属性,用于存储 Message 实例列表:

class MessageBoard : public QObject{ Q_OBJECT Q_PROPERTY(QQmlListProperty<Message> messages READ messages)public: QQmlListProperty<Message> messages() { return QQmlListProperty<Message>(this, 0, &MessageBoard::append_message); }private: static void append_message(QQmlListProperty<Message> *list, Message *msg) { MessageBoard *msgBoard = qobject_cast<MessageBoard *>(list->object); if (msg) msgBoard->m_messages.append(msg); } QList<Message *> m_messages;};

QQmlListProperty 的模板类类型(在本例中为 Message)必须在 QML 类型系统中注册。

1.5、分组属性

任何只读的对象类型属性都可以作为分组属性从 QML 代码访问。这可用于公开一组相关属性,这些属性描述了类型的一组属性。

例如,假设 Message::author 属性的类型是 MessageAuthor 而不是简单的字符串,具有 name 和 email 的子属性:

class MessageAuthor : public QObject{ Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(QString email READ email WRITE setEmail)public: ...};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;};

可以使用 QML 中的分组属性语法编写 author 属性:

Message { author.name: "怡然的导师" author.email: "alexandra@mail.com"}

分组属性是只读的,并且在构造时由父对象初始化为有效值。

分组属性的子属性可以从 QML 修改,但分组属性对象本身永远不会改变,

二、暴露方法

QObject 派生类型的任何方法都可以从 QML 代码访问,只要它满足其中一项:

Q_INVOKABLE() 宏标记的公共方法作为 public slot 的方法

例如,下面的 MessageBoard 类有一个使用 Q_INVOKABLE 宏标记的 postMessage() 方法,以及一个公共槽的 refresh() 方法:

class MessageBoard : public QObject{ Q_OBJECTpublic: Q_INVOKABLE bool postMessage(const QString &msg) { qDebug() << "Called the C++ method with" << msg; return true; }public slots: void refresh() { qDebug() << "Called the C++ slot"; }};

如果将 MessageBoard 的实例设置为文件 MyItem.qml 的上下文数据,则 MyItem.qml 可以调用两个方法,如下例所示:

int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); MessageBoard msgBoard; QQuickView view; view.engine()->rootContext()->setContextProperty("msgBoard", &msgBoard); view.setSource(QUrl::fromLocalFile("MyItem.qml")); view.show(); return app.exec();} // MyItem.qmlimport QtQuick 2.0Item { width: 100; height: 100 MouseArea { anchors.fill: parent onClicked: { var result = msgBoard.postMessage("Hello from QML") console.log("Result of postMessage():", result) msgBoard.refresh(); } }}

如果 C++ 方法具有 QObject* 类型的参数,则可以使用对象 id 或引用该对象的 JavaScript 变量值从 QML 传递参数值。

QML 支持调用重载的 C++ 函数。 如果存在多个同名但参数不同的 C++ 函数,则会根据提供的参数数量和类型调用正确的函数。

当从 QML 中的 JavaScript 表达式访问时,从 C++ 方法返回的值将转换为 JavaScript 值。

三、暴露信号

QObject 派生类型的任何公共信号都可以从 QML 代码访问。

QML 引擎自动为从 QML 使用的 QObject 派生类型的任何信号创建信号处理程序。信号处理程序始终命名为 on<Signal>,其中 <Signal> 是信号的名称,首字母大写。 信号传递的所有参数都可以通过参数名称在信号处理程序中使用。

例如,假设 MessageBoard 类有一个带有单个参数主题的 newMessagePosted() 信号:

class MessageBoard : public QObject{ Q_OBJECTpublic: // ...signals: void newMessagePosted(const QString &subject);};

 如果 MessageBoard 类型已注册到 QML 类型系统,则在 QML 中声明的 MessageBoard 对象可以使用名为 onNewMessagePosted 的信号处理程序接收 newMessagePosted() 信号,并检查主题参数值:

MessageBoard { onNewMessagePosted: (subject)=> console.log("New message received:", subject)}

与属性值和方法参数一样,信号参数必须具有 QML 引擎支持的类型。(使用未注册的类型不会产生错误,但处理程序将无法访问参数值。)

请注意,QML引擎无法区分名称相同但参数不同的信号,类可能有多个同名的信号,但只有最后一个信号可以作为 QML 信号访问。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。