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)

相关推荐

  • 井川,日本有没有“常叶”这个姓

    技术井川,日本有没有“常叶”这个姓鹤田 香取 野泽 麻生 小田切 草翦 稻垣 木村 中居 濑户 山下 酒井 松本 石田 柴崎 藤原 福山 江口 唐泽 长泽 椎名 松岛 白石 铃木

    生活 2021年10月28日
  • 在家里挣钱的办法,2020年能在家挣钱的方法

    技术在家里挣钱的办法,2020年能在家挣钱的方法1/6 开网店。全职妈妈在家赚钱可以采用开网店的方式。假如你有资金在家里挣钱的办法,假如你有做生意的头脑,不如去开一个网店吧,利用自己的空余时间去网店上赚点零花钱,还是很

    生活 2021年10月28日
  • 怎样鉴别银手镯的真假,如何鉴定自己买的银手镯是真假

    技术怎样鉴别银手镯的真假,如何鉴定自己买的银手镯是真假颜色怎样鉴别银手镯的真假、柔韧性好在挑选白银手镯时,首先可以看它的颜色,纯度越高,颜色就越洁白,但很容易被氧化,而呈现黑色,尽管被氧化过色泽有些黑但很光亮。真正的纯银

    生活 2021年10月30日
  • html中em是什么单位(em值是什么意思)

    技术css3中em指的是什么单位小编给大家分享一下css3中em指的是什么单位,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧! 在css3中,em是一个相对长度单位,相对于当前

    攻略 2021年12月19日
  • postman自动调用获取token

    技术postman自动调用获取token postman自动调用获取tokenPostman不光支持单次请求,还支持环境变量、全局变量、集合变量
    本文使用Collection Variable
    Coll

    礼包 2021年12月2日
  • index

    技术index index!DOCTYPE html
    htmlheadmeta charset="utf-8" /title/titlelink rel="stylesheet" type="text/

    礼包 2021年10月27日