利用上下文属性将 C++ 对象嵌入 QML 里

目录
  • 一、设置简单的上下文属性
  • 二、将对象设置为上下文属性
  • 三、上下文属性与C++ 的数据模型示例
    • 3.1、字符串列表模型
    • 3.2、对象列表模型
    • 3.3、QAbstractItemModel

QQmlContext 类使将 C++ 数据注入 QML 对象的能力成为可能。此类向 QML 对象的上下文公开数据,以便可以直接从 QML 代码范围内引用数据。

一、设置简单的上下文属性

例如,这里有一个 QML 项,它引用了当前作用域中不存在的 currentDateTime 值:

// MyItem.qml
import QtQuick 2.0

Text
{
    text: currentDateTime
}

这个值可以由加载 QML 组件的 C++ 应用程序使用 QQmlContext::setContextProperty() 直接设置:

    QQuickView view;
    view.rootContext()->setContextProperty("currentDateTime",QDateTime::currentDateTime());
    view.setSource(QUrl::fromLocalFile("MyItem.qml"));
    view.show();

由于在 QML 中计算的所有表达式都是在特定上下文中计算的,如果修改了上下文,则将重新计算该上下文中的所有绑定。因此,应在应用程序初始化之外谨慎使用上下文属性,因为这可能会导致应用程序性能下降。

二、将对象设置为上下文属性

上下文属性可以包含 QVariant QObject* 值。 这意味着也可以使用这种方法注入自定义 C++ 对象,并且可以直接在 QML 中修改和读取这些对象。修改上面的例子,嵌入一个 QObject 实例而不是一个 QDateTime 值,QML 代码在对象实例上调用一个方法:

class ApplicationData : public QObject
{
    Q_OBJECT
public:
    Q_INVOKABLE QDateTime getCurrentDateTime() const
    {
        return QDateTime::currentDateTime();
    }
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    ApplicationData data;

    QQuickView view;
    view.rootContext()->setContextProperty("applicationData", &data);
    view.setSource(QUrl::fromLocalFile("MyItem.qml"));
    view.show();

    return app.exec();
}
// MyItem.qml
import QtQuick 2.0

Text
{
    text: applicationData.getCurrentDateTime()
}

请注意:从 C++ 返回到 QML 的日期/时间值可以通过 Qt.formatDateTime() 和相关函数进行格式化。

如果 QML 项需要从上下文属性接收信号,它可以使用 Connections 类型连接到它们。 例如,如果 ApplicationData 有一个名为 dataChanged() 的信号,则可以使用 Connections 对象中的 onDataChanged 处理程序连接到该信号:

Text
{
    text: applicationData.getCurrentDateTime()

    Connections
    {
        target: applicationData
        onDataChanged: console.log("The application data changed!")
    }
}

三、上下文属性与C++ 的数据模型示例

3.1、字符串列表模型

int main(int argc, char ** argv)
{
    QGuiApplication app(argc, argv);

    QStringList dataList;
    dataList.append("Item 1");
    dataList.append("Item 2");
    dataList.append("Item 3");
    dataList.append("Item 4");

    QQuickView view;
    QQmlContext *ctxt = view.rootContext();
    ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));

    view.setSource(QUrl("qrc:view.qml"));
    view.show();

    return app.exec();
}
import QtQuick 2.0

ListView
{
    width: 100; height: 100

    model: myModel
    delegate: Rectangle
    {
        height: 25
        width: 100
        Text { text: modelData }
    }
}

3.2、对象列表模型

#ifndef DATAOBJECT_H
#define DATAOBJECT_H

#include <QObject>

class DataObject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
public:
    DataObject(QObject *parent=nullptr);
    DataObject(const QString &name, const QString &color, QObject *parent=nullptr);

    QString name() const;
    void setName(const QString &name);

    QString color() const;
    void setColor(const QString &color);

signals:
    void nameChanged();
    void colorChanged();

private:
    QString m_name;
    QString m_color;
};

#endif // DATAOBJECT_H
#include <QDebug>
#include "dataobject.h"

DataObject::DataObject(QObject *parent)
    : QObject(parent)
{
}

DataObject::DataObject(const QString &name, const QString &color, QObject *parent)
    : QObject(parent), m_name(name), m_color(color)
{
}

QString DataObject::name() const
{
    return m_name;
}

void DataObject::setName(const QString &name)
{
    if (name != m_name)
    {
        m_name = name;
        emit nameChanged();
    }
}

QString DataObject::color() const
{
    return m_color;
}

void DataObject::setColor(const QString &color)
{
    if (color != m_color)
    {
        m_color = color;
        emit colorChanged();
    }
}
#include "dataobject.h"

int main(int argc, char ** argv)
{
    QGuiApplication app(argc, argv);

    QList<QObject*> dataList;
    dataList.append(new DataObject("Item 1", "red"));
    dataList.append(new DataObject("Item 2", "green"));
    dataList.append(new DataObject("Item 3", "blue"));
    dataList.append(new DataObject("Item 4", "yellow"));

    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);
    QQmlContext *ctxt = view.rootContext();
    ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));

    view.setSource(QUrl("qrc:view.qml"));
    view.show();

    return app.exec();
}
import QtQuick 2.0

ListView
{
    width: 100; height: 100

    model: myModel
    delegate: Rectangle
    {
        height: 25
        width: 100
        color: model.modelData.color
        Text { text: name }
    }
}

3.3、QAbstractItemModel

#include <QAbstractListModel>
#include <QStringList>

class Animal
{
public:
    Animal(const QString &type, const QString &size);
    QString type() const;
    QString size() const;

private:
    QString m_type;
    QString m_size;
};

class AnimalModel : public QAbstractListModel
{
    Q_OBJECT
public:
    enum AnimalRoles
    {
        TypeRole = Qt::UserRole + 1,
        SizeRole
    };

    AnimalModel(QObject *parent = nullptr);
    void addAnimal(const Animal &animal);
    int rowCount(const QModelIndex & parent = QModelIndex()) const;
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;

protected:
    QHash<int, QByteArray> roleNames() const;

private:
    QList<Animal> m_animals;
};
#include "model.h"

Animal::Animal(const QString &type, const QString &size)
    : m_type(type), m_size(size)
{
}

QString Animal::type() const
{
    return m_type;
}

QString Animal::size() const
{
    return m_size;
}

AnimalModel::AnimalModel(QObject *parent)
    : QAbstractListModel(parent)
{
}

void AnimalModel::addAnimal(const Animal &animal)
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_animals << animal;
    endInsertRows();
}

int AnimalModel::rowCount(const QModelIndex & parent) const
{
    Q_UNUSED(parent)
    return m_animals.count();
}

QVariant AnimalModel::data(const QModelIndex & index, int role) const
{
    if (index.row() < 0 || index.row() >= m_animals.count())
        return QVariant();

    const Animal &animal = m_animals[index.row()];
    if (role == TypeRole)
        return animal.type();
    else if (role == SizeRole)
        return animal.size();
    return QVariant();
}

QHash<int, QByteArray> AnimalModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[TypeRole] = "type";
    roles[SizeRole] = "size";
    return roles;
}
int main(int argc, char ** argv)
{
    QGuiApplication app(argc, argv);

    AnimalModel model;
    model.addAnimal(Animal("Wolf", "Medium"));
    model.addAnimal(Animal("Polar bear", "Large"));
    model.addAnimal(Animal("Quoll", "Small"));

    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);
    QQmlContext *ctxt = view.rootContext();
    ctxt->setContextProperty("myModel", &model);

    view.setSource(QUrl("qrc:view.qml"));
    view.show();

    return app.exec();
}
import QtQuick 2.0

ListView
{
    width: 200; height: 250

    model: myModel
    delegate: Text { text: "Animal: " + type + ", " + size }
}

到此这篇关于利用上下文属性将 C++ 对象嵌入 QML 里的文章就介绍到这了,更多相关  C++ 对象嵌入 QML 里内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 将 C++ 类型属性暴露给 QML

    目录 一.数据类型处理和所有权 1.1.暴露属性 1.2.使用通知信号的注意事项 1.3.具有对象类型的属性 1.4.具有对象列表类型的属性 1.5.分组属性 二.暴露方法 三.暴露信号 可以使用 C++ 代码中定义的功能轻松扩展 QML.由于 QML 引擎与 Qt 元对象系统的紧密集成,QObject 派生类公开的任何功能都可以从 QML 代码访问.这使得 C++ 数据和函数可以直接从 QML 访问,通常几乎不需要修改. QML 引擎能够通过元对象系统反射 QObject 实例.这意味着任何

  • 利用上下文属性将 C++ 对象嵌入 QML 里

    目录 一.设置简单的上下文属性 二.将对象设置为上下文属性 三.上下文属性与C++ 的数据模型示例 3.1.字符串列表模型 3.2.对象列表模型 3.3.QAbstractItemModel QQmlContext 类使将 C++ 数据注入 QML 对象的能力成为可能.此类向 QML 对象的上下文公开数据,以便可以直接从 QML 代码范围内引用数据. 一.设置简单的上下文属性 例如,这里有一个 QML 项,它引用了当前作用域中不存在的 currentDateTime 值: // MyItem.q

  • 利用上下文属性将 C++ 对象嵌入 QML 里

    目录 一.设置简单的上下文属性 二.将对象设置为上下文属性 三.上下文属性与C++ 的数据模型示例 3.1.字符串列表模型 3.2.对象列表模型 3.3.QAbstractItemModel QQmlContext 类使将 C++ 数据注入 QML 对象的能力成为可能.此类向 QML 对象的上下文公开数据,以便可以直接从 QML 代码范围内引用数据. 一.设置简单的上下文属性 例如,这里有一个 QML 项,它引用了当前作用域中不存在的 currentDateTime 值: // MyItem.q

  • 利用Java反射机制实现对象相同字段的复制操作

    一.如何实现不同类型对象之间的复制问题? 1.为什么会有这个问题? 近来在进行一个项目开发的时候,为了隐藏后端数据库表结构.同时也为了配合给前端一个更友好的API接口文档(swagger API文档),我采用POJO来对应数据表结构,使用VO来给传递前端要展示的数据,同时使用DTO来进行请求参数的封装.以上是一个具体的场景,可以发现这样子一个现象:POJO.VO.DTO对象是同一个数据的不同视图,所以会有很多相同的字段,由于不同的地方使用不同的对象,无可避免的会存在对象之间的值迁移问题,迁移的一

  • Java爬虫实现Jsoup利用dom方法遍历Document对象

    先给出网页地址: https://wall.alphacoders.com/featured.php?lang=Chinese 主要步骤: 利用Jsoup的connect方法获取Document对象 String html = "https://wall.alphacoders.com/featured.php?lang=Chinese"; Document doc = Jsoup.connect(html).get(); 内容过长,就不再显示. 我们以这部分为例: <ul cl

  • 详解利用上下文管理器扩展Python计时器

    目录 一个 Python 定时器上下文管理器 了解 Python 中的上下文管理器 理解并使用 contextlib 创建 Python 计时器上下文管理器 使用 Python 定时器上下文管理器 写在最后 上文中,我们一起学习了手把手教你实现一个 Python 计时器.本文中,云朵君将和大家一起了解什么是上下文管理器 和 Python 的 with 语句,以及如何完成自定义.然后扩展 Timer 以便它也可以用作上下文管理器.最后,使用 Timer 作为上下文管理器如何简化我们自己的代码. 上

  • JS Testing Properties 判断属性是否在对象里的方法

    Testing Properties To check whether an object has a property with a given name. You can do this with the in operator, with the hasOwnProperty() and propertyIsEnumerable() methods, 在JS中判断一个对象是否包含某个属性,可以使用 in,hasOwnProperty() and propertyIsEnumerable()

  • Gridview利用DataFormatString属性设置数据格式的方法

    本文实例讲述了Gridview利用DataFormatString属性设置数据格式的方法.分享给大家供大家参考,具体如下: 首先把Gridview的AutoGenerateColumns属性设为False(默认是False),DataField选择相应的字段,特别需要注意的是要把需要设置的字段的HtmlEncode属性设置为False,否则所设置的格式将无法显示,然后就可以设置每个字段的 DataFormatString属性来输出不同的格式了. DataFormatString 属性语法如下:

  • PHP动态地创建属性和方法, 对象的复制, 对象的比较,加载指定的文件,自动加载类文件,命名空间

    PHP前言: •动态地创建属性和方法 •对象的复制 •对象的比较 •加载指定的文件 •自动加载类文件 •命名空间 示例 1.类的相关知识点 3(动态地创建属性和方法) class/class3.php <?php /** * 类的相关知识点 3(动态地创建属性和方法) */ // 用于演示如何动态地创建属性(这就是 php 中所谓的重载) class Class1 { // __set 魔术方法,当设置的属性不存在或者不可访问(private)时就会调用此函数 public function _

  • Python 类属性与实例属性,类对象与实例对象用法分析

    本文实例讲述了Python 类属性与实例属性,类对象与实例对象用法.分享给大家供大家参考,具体如下: demo.py(类属性,所有实例对象共用类属性): # 定义工具类 继承object是为了兼容python2.x class Tool(object): # 使用赋值语句定义类属性,记录实例化工具对象的数量 count = 0 def __init__(self, name): self.name = name # 初始化方法内部定义及初始化实例属性 # 类名.类属性名 的方式访问类属性. To

  • vue利用v-for嵌套输出多层对象,分别输出到个表的方法

    如下所示: specifications:[ { specificationName:"颜色", specificationItem:[ {value:"黄色"}, {value:"黑色"} ] } ] <table class="table table-bordered table-hover table-item spggdytable" id="ggxtable" v-show="is

随机推荐