//Is this possible in any way?
//Q_PROPERTY(AnimalModel modelAnimals READ modelAnimals NOTIFY modelAnimalsChanged)
はいそれは、あなたがしようとしませんでしたか?もちろん、AnimalModel
ではなくAnimalModel *
となりますが、モデルがQAbstractListModel
を継承している限り、それだけで十分です。 NOTIFY
の部分も必要ありません。変更はモデルの内部に自動的に反映されるためです。 modelAnimalsChanged
は、モデル全体を別のモデルに置き換えた場合や、通知信号なしでプロパティを使用するというQMLの警告をシャットダウンする場合にのみ意味があります。モデルオブジェクトが変更されないときに後者を行うよりクリーンな方法は、スロットまたはQ_INVOKABLE
からAnimalModel *
を返すことです。
本当に柔軟なモデルが必要な場合は、QObject *
を保存し、QMLから任意のプロパティを持つ任意のオブジェクトを作成してモデルに追加することができます。モデルから、オブジェクトを返す単一のobject
ロールがあります。オブジェクトをクエリして、それを保持しているプロパティを取得することができます。 「古典的」リストモデルの実装では、静的で固定されたスキーマを持つモデルを定義しますが、このアプローチを使用すると、モデル内に異なるプロパティを持つ「アモルファス」オブジェクトを持つことができます。
当然ながら、このようなモデルでは、オブジェクトの種類ごとに安全性が必要です(たとえば、そのオブジェクトの各オブジェクトにproperty int type
)。これに基づいて、オブジェクトの使用可能なプロパティを決定できます。私の通常のやり方は、デリゲートのためにLoader
を持ち、そのインスタンスをインスタンス化するオブジェクトタイプを視覚化するさまざまなQML UI実装にデータソースとしてオブジェクトを渡すことです。この方法では、モデル内に異なるオブジェクトと、ビューデリゲートとして異なるQMLアイテムがあります。
リスト/モデルを動的に作成したり、QMLの宣言構文を使用したりすることができるように、最終的な "すべての取引のジャック"リスト/モデルオブジェクトを作成する最後のステップは、QQmlListProperty
とQ_CLASSINFO("DefaultProperty", "container")
を実装することです。また、このソリューションでは、そのようなモデルを追加または削除したり、宣言的にインスタンス化されたオブジェクトを削除したりすることもできます。
また、ご使用のシナリオに応じて、モデルにはqmlRegisterType()
またはqmlRegisterUncreatableType()
のいずれかが必要です。
いいえ、2番目の一見では、スキーマレスモデルではなく単に異なるスキーマモデルを意味する "データのモデル"のように見えます。その場合、AnimalModel *
を返す代わりにQAbstractListModel *
、さらにはQObject *
を使用することができます。メタシステムを使用してダイナミズムを使用するため、QMLで動作します。しかし、いずれにしても、スキーマレスモデルははるかに強力で柔軟性があり、C++コードを定義する必要はなく、すべてQMLだけで動作することができます。
その後
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> * pHash;
if (!pHash) {
pHash = new QHash<int, QByteArray>;
(*pHash)[Qt::UserRole + 1] = "object";
}
return *pHash;
}
int size() const { return _data.size(); }
QQmlListProperty<QObject> content() { return QQmlListProperty<QObject>(this, _data); }
public slots:
void add(QObject * o) {
int i = _data.size();
beginInsertRows(QModelIndex(), i, i);
_data.append(o);
o->setParent(this);
sizeChanged();
endInsertRows();
}
void insert(QObject * o, int i) {
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;
}
signals:
void sizeChanged();
};
、あなたはqmlRegisterType<List>("Core", 1, 0, "List");
あなたはかなりあなたがしたい任意の方法を使用することができます後 - それは自然にそれが直接ListView
を駆動するためのモデルとして使用することができますQMLs QtObject
を含め、任意のQObject
または派生を保持しますが。あなたはこのように、スロットまたは宣言を使用して動的に取り込むことができます。
List {
QtObject { ... }
QtObject { ... }
List {
QtObject { ... }
QtObject { ... }
}
}
また、オブジェクトの所有権を処理すると、あなたが簡単に巣にそれをすることができ、本質的に区画され、ツリーモデルを作成 - あなたがいない宣言ことに注意してくださいQMLのListModel
でそれを行います。 parentChanged
シグナルを追加し、変化する親に対してバインドしたい場合は、それを発行するセッターを実装することができますが、私の場合はそうではありませんでした。あなたがobjectName
プロパティまたはint type
プロパティを使用して、デリゲートのためLoader
を使用することができますいずれかのビューでそれを使用する方法のよう
、:
Loader {
width: childrenRect.width
height: childrenRect.height
}
オブジェクト名を使用する場合は、あなたが作りますローダーがname.qml
ファイルを作成し、intを使用する場合はComponent
の配列を作成し、適切なインデックスをソースコンポーネントとして使用できます。 object
をLoader
のプロパティとして公開し、実際のオブジェクトUIにparent.object.prop
を参照させるか、またはsetSource(name + ".qml", {"object": object})
を使用してオブジェクトのプロパティを直接その項目に入れることができます。setSource
はインラインComponent
ではなく外部ソースでのみ機能します。 s。外部ソースの場合、object
は何もせずに転送することができますが、何らかの理由でインラインコンポーネントでは機能しませんが、そのようなコンポーネントでは唯一可能な方法は、それをプロパティとして公開することですローダー。
非常に複雑な答えをお寄せいただきありがとうございます。根本的な問題が無効な 'Q_PROPERTY'型であったということは間違いありませんでした。 'AnimalModel *'では素晴らしい動作をします。 'QObject *'のモデルに関して、これは私がすでに持っているものです(stackoverflow.com/questions/35065627/...)。しかし、あなたは 'Q_CLASSINFO'と' qmlRegisterType'ユースケースについて具体例を投稿したり、より具体的にしていただけますか?面白いようですが、私はこのケースでどのように正確に使用するのかよく分かりません。 –
@LudekVodicka - 私はいくつかのコードを追加しました。同様の解決策を探している人がコードにアクセスしやすいように、質問のタイトルを変更する自由を取った。 – dtech
これは絶対に傑作です。私は先月、Qmlを学んでいて、そのような素晴らしい方法で組み合わせることができないと思っていませんでした。説明と例をありがとう。私の心に唯一の質問です。静的ではなく静的なptrとしてQHashMapを使用するのはなぜですか?静的なQHash roles = {{ObjectRole、 "object}};'と定義することは可能ですが、C++ 11が必要です。これが理由でしたか? –