久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

如何創建用于 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 ()?環形?)
主站蜘蛛池模板: 国外成人在线视频 | 久久久亚洲精品视频 | 性国产xxxx乳高跟 | 精品一区av| 色视频在线播放 | 一区在线播放 | 欧美日韩在线免费 | 日韩不卡视频在线观看 | 99爱免费| 亚洲精品视频导航 | 久久精片| 久久91| 久久久久久免费毛片精品 | 亚洲成人自拍 | 黄色大片免费网站 | 国产精品一区二区久久久久 | 美国一级毛片a | 日韩一区二区三区四区五区 | 亚洲国产精品一区二区久久 | 精品日韩一区二区三区av动图 | 老牛嫩草一区二区三区av | 欧美日韩精品免费 | 国产一区欧美一区 | 999久久久久久久久6666 | av大全在线 | 91精品国产色综合久久不卡98 | 欧洲精品码一区二区三区免费看 | 欧美黄视频 | 一呦二呦三呦国产精品 | 欧美成人免费在线 | 一二区视频| 国产精品久久久久久久久久 | 综合久久综合久久 | 成人一区二区电影 | 日本一区二区三区免费观看 | 国产剧情一区 | 狠狠色网 | 在线观看av不卡 | 国产精品成人一区二区三区 | 亚洲精品乱码久久久久久蜜桃 | 国产午夜久久 |