pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

如何創建用于 QML 的通用對象模型?

How to create a generic object model for use in QML?(如何創建用于 QML 的通用對象模型?)
本文介紹了如何創建用于 QML 的通用對象模型?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我想知道是否有任何宏或方法如何將Qt模型注冊為QObject的屬性.

I would like to know if there is any macro or way how to register Qt model as property of QObject.

例如,我有 AnimalModel (http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel).

我知道我可以將它傳遞給 QuickView 的根上下文

I Know I can pass it to root context of QuickView

QuickView view;
view.rootContext()->setContextProperty("myModel", &model);

如果我通過 Qml 宏注冊了 QObject,我也可以傳遞這個對象來查看:

In case I have QObject registered via Qml macros, I can pass this object to view too:

view.rootContext()->setContextProperty("obj", pDataObject);

但是如果我想要擁有任何數據模型的 QObject 怎么辦?

But what If I want to have QObject which holds model of any data?

例如:

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)
    ...

    AnimalModel m_modelAnimals;

    //Is this possible in any way?
    //Q_PROPERTY(AnimalModel modelAnimals READ modelAnimals NOTIFY modelAnimalsChanged)
};

到目前為止,我發現的每個示例都展示了如何將 QAbstractListModel 傳遞給根上下文.但沒有如何將其用作 QObject 屬性.

Every example I found until now shows how to pass QAbstractListModel to root context. But none how to use it as QObject property.

(我知道有 QQmlListPropertyQQmlListProperty 不支持部分刷新.重建所有 Qml 對象總是必要的)

(I know there is QQmlListProperty but QQmlListProperty doesn't support partial refresh. It's always necessary to rebuild all Qml objects)

推薦答案

//Is this possible in any way?
//Q_PROPERTY(AnimalModel modelAnimals READ modelAnimals NOTIFY modelAnimalsChanged)

是的,你沒有嘗試過嗎?當然,它不會是AnimalModel,而是AnimalModel *,但只要模型繼承了QAbstractListModel,就夠了.您甚至不需要 NOTIFY 部分,因為無論如何都會自動反映模型內部的更改.modelAnimalsChanged 僅在您用不同的模型替換整個模型時才有意義,并且自然而然地關閉 QML 關于在沒有通知信號的情況下使用屬性的警告.當模型對象沒有改變時,執行后者的一種更簡潔的方法是從插槽或 Q_INVOKABLE 返回一個 AnimalModel *.

Yes it is, didn't you try? Of course, it will not be a AnimalModel but a AnimalModel *, but as long as the model inherits QAbstractListModel, that's all you need. You don't even need the NOTIFY part, as changes, internal to the model will be automatically reflected anyway. modelAnimalsChanged only makes sense when you replace the entire model with a different model, and naturally, to shut up QML's warnings about using a property without a notify signal. A cleaner way to do the latter when the model object doesn't change is to just return a AnimalModel * from a slot or a Q_INVOKABLE.

如果你想要一個真正靈活的模型,你可以制作一個存儲 QObject * 的模型,然后你可以從 QML 創建具有任意屬性的任意對象,并添加到模型中.然后從模型中,您有一個返回對象的 object 角色,您可以查詢和使用該對象來檢索它所擁有的屬性.經典"列表模型實現將定義一個具有靜態、固定模式的模型,而使用這種方法允許在模型中擁有具有不同屬性的無定形"對象.

If you want a truly flexible model, you can make one that stores QObject *, then from QML you can create arbitrary objects with arbitrary properties, and add to the model. Then from the model you have a single object role which returns the object, and you can query and use the object to retrieve the properties it holds. Whereas a "classical" list model implementation will define a model with a static, fixed schema, using this approach allows to have "amorphous" objects in the model with different properties.

自然,這需要某種類型安全性,例如為此類模型中的每個對象都有一個 property int type,然后您可以根據它確定對象的可用屬性.我通常的方法是為委托提供一個 Loader,并將對象作為數據源傳遞給不同的 QML UI 實現,以可視化它實例化的對象類型.這樣一來,模型中就有不同的對象,也有不同的 QML 項作為視圖委托.

Naturally, this requires some type safety, for example have a property int type for each object in such a model, and based on it you can determine the available properties for the object. My usual approach is to have a Loader for a delegate, and have it pass the object as a data source to different QML UI implementations visualizing that object type that it instantiates. This way you have both different objects in the model, and different QML items as view delegates.

制作終極萬事通"列表/模型對象的最后一步是實現 QQmlListPropertyQ_CLASSINFO("DefaultProperty", "container")它允許您動態地組合列表/模型,或使用 QML 的聲明性語法.另請注意,使用此解決方案,您可以在此類模型中添加或刪除,甚至刪除聲明式實例化對象.

The last step to making the ultimate "jack of all trades" list/model object is to implement QQmlListProperty and Q_CLASSINFO("DefaultProperty", "container") for it, allowing you to both compose the list/model dynamically, or using QML's declarative syntax. Also note that with this solution, you can add to or remove from such a model, even remove declaratively instantiated objects.

此外,根據您的使用場景,您可能需要為模型使用 qmlRegisterType()qmlRegisterUncreatableType().

Also, depending on your usage scenario, you may have to either qmlRegisterType() or qmlRegisterUncreatableType() for the model.

好吧,乍一看,任何數據的模型"似乎并不是指無模式模型,而是指不同的模式模型.在這種情況下,您可以使用 QAbstractListModel * 甚至 QObject * 而不是返回 AnimalModel * - 它無論如何都可以在 QML 中工作,因為它通過元系統使用動態.但無論如何,無模式模型更加強大和靈活,它們不需要定義 C++ 代碼,它可以單獨使用 QML 來工作.

OK, on a second glance, it looks like by "model of any data" you didn't mean schema-less models but simply different schema models. In that case, instead of returning an AnimalModel *, you can use a QAbstractListModel * or even a QObject * - it will work in QML anyway, as it employs dynamism through the meta system. But at any rate, schema-less models are that much more powerful and flexible, and they don't need C++ code to be defined, it can all work from QML alone.

class List : public QAbstractListModel {
    Q_OBJECT
    QList<QObject *> _data;

    Q_PROPERTY(int size READ size NOTIFY sizeChanged)
    Q_PROPERTY(QQmlListProperty<QObject> content READ content)
    Q_PROPERTY(QObject * parent READ parent WRITE setParent)
    Q_CLASSINFO("DefaultProperty", "content")
public:
    List(QObject *parent = 0) : QAbstractListModel(parent) { }
    int rowCount(const QModelIndex &p) const { Q_UNUSED(p) return _data.size(); }
    QVariant data(const QModelIndex &index, int role) const {
        Q_UNUSED(role)
        return QVariant::fromValue(_data[index.row()]);
    }
    QHash<int, QByteArray> roleNames() const {
        static QHash<int, QByteArray> roles = { { Qt::UserRole + 1, "object" } };
        return roles;
    }
    int size() const { return _data.size(); }
    QQmlListProperty<QObject> content() { return QQmlListProperty<QObject>(this, _data); }

public slots:
    void add(QObject * o) { insert(o, _data.size()); }

    void insert(QObject * o, int i) {
        if (i < 0 || i > _data.size()) i = _data.size();
        beginInsertRows(QModelIndex(), i, i);
        _data.insert(i, o);
        o->setParent(this);
        sizeChanged();
        endInsertRows();
    }

    QObject * take(int i) {
        if ((i > -1) && (i < _data.size())) {
            beginRemoveRows(QModelIndex(), i, i);
            QObject * o = _data.takeAt(i);
            o->setParent(0);
            sizeChanged();
            endRemoveRows();
            return o;
        } else qDebug() << "ERROR: take() failed - object out of bounds!";
        return 0;
    }

    QObject * get(int i) {
        if ((i > -1) && (i < _data.size())) return _data[i];
        else  qDebug() << "ERROR: get() failed - object out of bounds!";
        return 0;
    }

    void internalChange(QObject * o) { // added to force sort/filter reevaluation
      int i = _data.indexOf(o);
      if (i == -1) {
        qDebug() << "internal change failed, obj not found";
        return;
      } else {
        dataChanged(index(i), index(i));
      }
    }

signals:
    void sizeChanged();
};

然后,在你 qmlRegisterType("Core", 1, 0, "List"); 之后,你幾乎可以以任何你想要的方式使用它 - 它會保存任何 QObject 或者派生的,自然包括QMLs QtObject 可以直接作為模型來驅動ListView.您可以使用插槽或聲明式動態填充它,如下所示:

Then, after you qmlRegisterType<List>("Core", 1, 0, "List"); you can use it pretty much any way you want to - it will hold any QObject or derived, naturally including QMLs QtObject It can directly be used as a model to drive a ListView. You can populate it dynamically using the slots or declarative, like this:

List {
    QtObject { ... }
    QtObject { ... }
    List {
        QtObject { ... }
        QtObject { ... }
    }
}

它還將處理對象所有權,您可以輕松嵌套它,從本質上生成一個分區樹模型 - 請注意,您不能使用 QML 的 ListModel 聲明性地執行此操作.您可能想要添加一個 parentChanged 信號并實現一個發出它的 setter,如果您想綁定一個變化的父級,這在我的情況下是沒有必要的.

It will also handle object ownership, and you can easily nest it, producing in essence a compartmentalized tree model - note that you can't declaratively do that with QML's ListModel. You may want to add a parentChanged signal and implement a setter that emits it if you want to bind against a changing parent, it was not necessary in my case.

至于如何在視圖中使用它,您可以使用 objectName 屬性或 int type 屬性或基本上任何方法來區分不同的對象類型,并為委托使用 Loader:

As of how to use it with a view, you can either use the objectName property or an int type property or basically any means to discern between different object types, and use a Loader for the delegate:

Loader {
    // using component in order to capture context props and present to the variable delegate
    sourceComponent: Qt.createComponent(obj.objectName + ".qml")
    // if that is not needed simply use
    // source: obj.objectName + ".qml"
    // or setSource to pass specific properties to delegate properties
    // Component.onCompleted: setSource(obj.objectName + ".qml", {/*prop list*
                
【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數據?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環: for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環?)
Reusing thread in loop c++(在循環 C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環形?)
主站蜘蛛池模板: 火锅底料批发-串串香技术培训[川禾川调官网] | 尾轮组_头轮组_矿用刮板_厢式刮板机_铸石刮板机厂家-双驰机械 | 合肥风管加工厂-安徽螺旋/不锈钢风管-通风管道加工厂家-安徽风之范 | 国产液相色谱仪-超高效液相色谱仪厂家-上海伍丰科学仪器有限公司 | 超声波清洗机_超声波清洗机设备_超声波清洗机厂家_鼎泰恒胜 | 小型高低温循环试验箱-可程式高低温湿热交变试验箱-东莞市拓德环境测试设备有限公司 | 电脑刺绣_绣花厂家_绣花章仔_织唛厂家-[源欣刺绣]潮牌刺绣打版定制绣花加工厂家 | 塑料熔指仪-塑料熔融指数仪-熔体流动速率试验机-广东宏拓仪器科技有限公司 | 考勤系统_考勤管理系统_网络考勤软件_政企|集团|工厂复杂考勤工时统计排班管理系统_天时考勤 | 岛津二手液相色谱仪,岛津10A液相,安捷伦二手液相,安捷伦1100液相-杭州森尼欧科学仪器有限公司 | 骨密度检测仪_骨密度分析仪_骨密度仪_动脉硬化检测仪专业生产厂家【品源医疗】 | 全国国际化学校_国际高中招生_一站式升学择校服务-国际学校网 | 铜镍-康铜-锰铜-电阻合金-NC003 - 杭州兴宇合金有限公司 | 南京雕塑制作厂家-不锈钢雕塑制作-玻璃钢雕塑制作-先登雕塑厂 | 轴承振动测量仪电箱-轴承测振动仪器-测试仪厂家-杭州居易电气 | 阿里巴巴诚信通温州、台州、宁波、嘉兴授权渠道商-浙江联欣科技提供阿里会员办理 | 聚氨酯保温钢管_聚氨酯直埋保温管道_聚氨酯发泡保温管厂家-沧州万荣防腐保温管道有限公司 | 无菌水质袋-NASCO食品无菌袋-Whirl-Pak无菌采样袋-深圳市慧普德贸易有限公司 | 电杆荷载挠度测试仪-电杆荷载位移-管桩测试仪-北京绿野创能机电设备有限公司 | CTP磁天平|小电容测量仪|阴阳极极化_双液系沸点测定仪|dsj电渗实验装置-南京桑力电子设备厂 | 地磅-地秤-江阴/无锡地磅-江阴天亿计量设备有限公司_ | 共享雨伞_共享童车_共享轮椅_共享陪护床-共享产品的领先者_有伞科技 | 断桥铝破碎机_发动机破碎机_杂铝破碎机厂家价格-皓星机械 | 光伏家 - 太阳能光伏发电_分布式光伏发电_太阳能光伏网 | 蜘蛛车-登高车-高空作业平台-高空作业车-曲臂剪叉式升降机租赁-重庆海克斯公司 | 济南玻璃安装_济南玻璃门_济南感应门_济南玻璃隔断_济南玻璃门维修_济南镜片安装_济南肯德基门_济南高隔间-济南凯轩鹏宇玻璃有限公司 | 砂尘试验箱_淋雨试验房_冰水冲击试验箱_IPX9K淋雨试验箱_广州岳信试验设备有限公司 | 订做不锈钢_不锈钢定做加工厂_不锈钢非标定制-重庆侨峰金属加工厂 | 冷凝锅炉_燃气锅炉_工业燃气锅炉改造厂家-北京科诺锅炉 | 河南彩印编织袋,郑州饲料编织袋定制,肥料编织袋加工厂-盛军塑业 河南凯邦机械制造有限公司 | 大流量卧式砂磨机_强力分散机_双行星双动力混合机_同心双轴搅拌机-莱州市龙跃化工机械有限公司 | MES系统-WMS系统-MES定制开发-制造执行MES解决方案-罗浮云计算 | 曙光腾达官网-天津脚手架租赁-木板架出租-移动门式脚手架租赁「免费搭设」 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 蔬菜清洗机_环速洗菜机_异物去除清洗机_蔬菜清洗机_商用洗菜机 - 环速科技有限公司 | 吸污车_吸粪车_抽粪车_电动三轮吸粪车_真空吸污车_高压清洗吸污车-远大汽车制造有限公司 | 泰国试管婴儿_泰国第三代试管婴儿_泰国试管婴儿费用/多少钱_孕泰来 | 深圳快餐店设计-餐饮设计公司-餐饮空间品牌全案设计-深圳市勤蜂装饰工程 | 东莞市超赞电子科技有限公司 全系列直插/贴片铝电解电容,电解电容,电容器 | 乐考网-银行从业_基金从业资格考试_初级/中级会计报名时间_中级经济师 | 口信网(kousing.com) - 行业资讯_行业展会_行业培训_行业资料 |