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



















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








All Articles