c++编译器(c++用什么软件编程)

技术将C++ 类型属性暴露给QML的示例分析这期内容当中小编将会给大家带来有关将C++ 类型属性暴露给QML的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、数据类型处理和所

本期,边肖将给大家带来一个将C型属性暴露给QML的实例分析。文章内容丰富,从专业角度进行分析和描述。希望你看完这篇文章能有所收获。

00-1010从C传输到QML的任何数据,无论是作为属性值、方法参数或返回值,还是信号参数值,都必须是QML引擎支持的类型。

默认情况下,该引擎支持许多Qt C类型,当从QML使用时,可以自动适当地转换它们。

00-1010您可以使用Q_PROPERTY()宏来指定QObject的任何派生类的属性。

例如,这里有一个带有作者属性的消息类。如Q_PROPERTY宏调用所指定的,此属性可由author()方法读取,并由setAuthor()方法编写:

注意:不应该使用typedef或使用来指定Q_PROPERTY类型,因为它们会混淆moc。这可能会导致某些类型的比较失败。

错误用法:

使用foo enum=foo : enum;

classBar:publicQObject

{

Q_OBJECT

q _ PROPERTY(fooenumenumreadenumritesetenumnotifyeenumchanged)

};正确用法:

classBar:publicQObject

{

Q_OBJECT

q _ PROPERTY(foo : enumenumreadunmwritesetenumnotifyienumchanged)

};暴露属性实例:

classMessage:publicQObject

{

Q_OBJECT

q _ PROPERTY(QStringauthorREADauthorWRITEsetAuthorNOTIFYauthorChanged)

公众号:

空隙集作者(constQStringa)

{

如果(a!=m_author)

{

m _ author=a;

emitAuthorChanged();

}

}

QStringauthor()常量

{

returnm _ author

   }
signals:
    void authorChanged();
private:
    QString m_author;
};

如果在从 C++ 加载名为 MyItem.qml 的文件时将此类的实例设置为上下文属性:

int main(int argc, char *argv[]) 
{
    QGuiApplication app(argc, argv);
 
    QQuickView view;
    Message msg;
    view.engine()->rootContext()->setContextProperty("msg", &msg);
    view.setSource(QUrl::fromLocalFile("MyItem.qml"));
    view.show();
 
    return app.exec();
}
然

可以从 MyItem.qml 中读取 author 属性:

// MyItem.qml
import QtQuick 2.0
 
Text 
{
    width: 100; height: 100
    text: msg.author    // 调用 Message::author() 来获取这个值
 
    Component.onCompleted: 
    {
        msg.author = "Jonah"  // 调用 Message::setAuthor()    
    }
}

为了实现C++与 QML 的最大互操作性,任何可写的属性都应该有一个关联的 NOTIFY 信号,该信号在属性值更改时发出。这允许属性与属性绑定一起使用,这是 QML 的一个基本特性,它通过在任何依赖项的值发生变化时自动更新属性来强制执行属性之间的关系。即发出信号会通知 QML 引擎更新任何涉及属性的绑定。

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

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

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

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

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

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

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: "Alexandra"
    author.email: "alexandra@mail.com"
}

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

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

二、暴露方法

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

  • Q_INVOKABLE() 宏标记的公共方法

  • 作为 public slot 的方法

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

class MessageBoard : public QObject
{
    Q_OBJECT
public:
    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.qml
import QtQuick 2.0
 
Item 
{
    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_OBJECT
public:
   // ...
signals:
   void newMessagePosted(const QString &subject);
};

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

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

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

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

上述就是小编为大家分享的将C++ 类型属性暴露给QML的示例分析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/147371.html

(0)

相关推荐

  • 如何使用VBS遍历文件或文件夹路径输入文件的所有绝对路径

    技术如何使用VBS遍历文件或文件夹路径输入文件的所有绝对路径这篇文章给大家分享的是有关如何使用VBS遍历文件或文件夹路径输入文件的所有绝对路径的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。源码

    攻略 2021年11月1日
  • 如何使用Java的MD5工具类和客户端测试类

    技术Java的MD5工具类和客户端测试类怎么使用这篇文章主要讲解了“Java的MD5工具类和客户端测试类怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java的M

    攻略 2021年12月16日
  • Cortex-M0中断控制和系统控制,二)

    技术Cortex-M0中断控制和系统控制,二) Cortex-M0中断控制和系统控制(二)转载:https://aijishu.com/a/1060000000237975
    每一个外部中断都有一个对应的

    礼包 2021年11月30日
  • vue如何获取dom元素

    技术vue如何获取dom元素这篇文章将为大家详细讲解有关vue如何获取dom元素,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 vue获取dom元素的方法:

    攻略 2021年10月27日
  • swing入门到精通教程(怎么让程序用swing实现)

    技术怎么分析Swing体系结构今天就跟大家聊聊有关怎么分析Swing体系结构,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Swing体系结构最初Smalltalk

    攻略 2021年12月18日
  • 星期4英文,星期四的英文单词缩写是什么

    技术星期4英文,星期四的英文单词缩写是什么星期四的英文单词为Thursday 星期4英文,单词缩写为Thur. 【Thursday】
    是一个英文单词,中文意义为星期四或称礼拜四,指的是一周中星期三之后、星期五之前的那一

    生活 2021年10月22日