C ++およびQtQuickでQ_GADGETを使用する

Runetフォーラムを見ると、人々はC ++とQt Quickで書き始め 、いわゆる値型のためにQObjectの相続人を使用しています。 Martin Fowlerは、それらをValue Objectと呼びます。 Q_GADGETマクロがありますが、 QMetaObjectを使用するにはいくつかの制限がありますが、 QObjectからの継承はありません。 以下で説明するのは、Qt Quickを使用した実験の結果です。 コメントから何か新しいことを学ぶことができてうれしいです。


そのようなタイプの例は、QPoint、QGeoCoordinateなどです。 QObjectから継承してQ_OBJECTマクロを使用すること 、これらのタイプに不便です。



Q_GADGETを使用すると、次を使用できます。



制限:



アプリケーションがサーバーからのものを表示するだけであれば、構造を作成できます。


struct PlayItem { private: Q_GADGET Q_PROPERTY(int episode MEMBER episode) Q_PROPERTY(QString mp4Url MEMBER mp4Url) Q_PROPERTY(QString name MEMBER name) public: int episode; QString mp4Url; QString name; static PlayItem fromJson(const QJsonObject& jobj); }; Q_DECLARE_METATYPE(PlayItem) 

ここでQ_DECLARE_METATYPEを使用して、タイプをQVariantに登録します 。 なぜここで必要なのか、詳しくは後で説明します。


そのようなタイプは、他のオブジェクトのプロパティで使用できます。


 class Size { Q_GADGET public: Q_INVOKABLE quint16 rows() const noexcept; Q_INVOKABLE quint16 column() const noexcept; Q_INVOKABLE bool isNull() const noexcept; //.. }; class Crossword: public QObject { Q_OBJECT Q_PROPERTY(Size size READ size) public: Crossword(QObject* parent = nullptr); Size size() const noexcept; } 

そして、jsで静かに作業します。


 var csize = crossword.size; //... rows = csize.rows(); column = csize.column(); 

Q_GADGETおよびQ_INVOKABLE


何らかの理由で、 Q_INVOKABLEとマークされたメソッドでValueTypeを使用できません。 そのために、ValueTypeでQVariantを返すことができます! また、jsでも使用します! これは、多くのロールとスイッチではなく、モデルで非常に便利です。


 QVariant BucketModel::data(const QModelIndex &index, int role) const { switch (role) { case Bucket: return QVariant::fromValue(m_buckets[index.row()]); default: return QVariant(); } } QHash<int, QByteArray> BucketModel::roleNames() const { static const QHash<int, QByteArray> roles = { {Bucket, "bucket" } }; return roles; }; 

通常どおり、デリゲートで:


 delegate: ItemDelegate { width: parent.width text: bucket.name Image{ visible: bucket.id === b2App.settings.bucketId anchors{ right:parent.right verticalCenter: parent.verticalCenter margins: 8 } source: "qrc:/icons/tick/tick.png" } 

アイテムプロパティ


そのようなタイプはプロパティとして使用し、それらにバインドできます。 これは、ジェネリック型を介して行われます。


 Item { property var film //... Label { text: film.year //... } Label { text: film.countries //... } //... } 

タイプはインスタンス化の前にはわからないため、 TypeError: Cannot read property 'year' of undefinedに誓う(しかし落ちない) TypeError: Cannot read property 'year' of undefined


いくつかのインスタンスでプロパティを初期化することにより、この不正を削除できます。


 QQmlApplicationEngine engine; Film film; engine.rootContext()->setContextProperty("emptyFilm", QVariant::fromValue(film)); 

 Item { property var film: emptyFilm //... Label { text: film.year //... } Label { text: film.countries //... } //... } 

StackViewを使用する場合、これは非常に便利であることがわかります。ある画面では、最小限の情報でモデルを表示し、次の画面ではより詳細に表示します。




私個人の意見では、そのような値型は非常に便利です。



Source: https://habr.com/ru/post/J307816/


All Articles