29

C++ でリストを持っている場合、それを QML (Qt5 / QtQuick 2) に公開するにはどうすればよいですか? QObjectQML は派生クラスしか理解できないようです。これは、s を a に入れたりコピーしたりQObjectできないため、問題です。QListこれを行うにはどうすればよいですか:

struct Thing
{
    int size;
    QString name;
};

class ThingManager : public QObject
{
    Q_OBJECT

    // These macros support QtQuick, in case we one day want to use it to make a slick
    // interface (when QML desktop components are released).
    Q_PROPERTY(QList<Thing> things READ things NOTIFY thingssChanged)

public:
    // ...
    QList<Thing> things() const;

    // ...

};

QMLでこのようなことができるように:?

var a = thingManager.things[0].name;
4

9 に答える 9

26

QVariantListまたは、 ( )を使用することもできますQList<QVariant>。QML に渡されると自動的に JavaScript 配列に変更され、C++ および QML から読み書き可能になります。

于 2013-01-14T16:09:49.897 に答える
9

QML の経験を重ねた結果、もののリストを作成する最良の方法はQAbstractListModel.

Thing派生元を作成して、 (登録後)QObjectに格納できるようにします。その後、モデル アイテムとしてQVariant実際のアイテムを返すことができます。asThingでアクセスできます。リストの長さは として利用できます。Repeatermodel.display.a_property_of_thingmodel.count

これには、次の長所と短所があります。

  1. 高速 - リスト全体をコピーして 1 つの要素にアクセスするわけではありません。
  2. リストへの変更 (アイテムの追加、再配置、および削除) のアニメーションを簡単に取得できます。
  3. QML から簡単に使用できます。
  4. アニメーションを有効にするには、リストを変更するたびに、少し面倒な簿記 (beginInsertRows()など)を行う必要があります。

...

class Things : public QObject
{
...
};

Q_DECLARE_METATYPE(Thing*)

class ThingList : public QAbstractListModel
{
    Q_OBJECT
    
public:
    explicit ThingList(QObject *parent = 0);
    ~ThingList();

    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;

public slots:

    // Extra function to get the thing easily from outside Repeaters.
    Thing* thing(int idx);

private:
    QList<Thing*> mThings;
};

int ThingList::rowCount(const QModelIndex& parent) const
{
    return mThings.size();
}

QVariant ThingList::data(const QModelIndex& index, int role) const
{
    int i = index.row();
    if (i < 0 || i >= mThings.size())
        return QVariant(QVariant::Invalid);

    return QVariant::fromValue(mThings[i]);
}

Thing* ThingList::thing(int idx)
{
    if (idx < 0 || idx >= mThings.size())
        return nullptr;

    return mThings[idx];
}
于 2014-12-11T08:54:50.147 に答える
5

ああ、私は答えを見つけました(私は、テストされていないと思います):QQmlListProperty

例にはいくつかの使用法があります。たとえば、次のqtdeclarative/examples/quick/tutorials/gettingStartedQml/filedialog/directory.*とおりです。

残念ながら、現時点では読み取り専用リストしか作成できません。

于 2013-01-11T23:39:09.367 に答える
3

あなたはQObjectについてかなり間違っています。以下が完全に機能するように、単にポインタの形でQListに与えることができます:

class Thing : public QObject
{
    Q_OBJECT

    Q_PROPERTY (int     size READ getSize CONSTANT)
    Q_PROPERTY (QString name READ getName CONSTANT)

public:
    Thing(QObject * parent = NULL) : QObject(parent) {}

    int     getSize () const { return m_size; }
    QString getName () const { return m_name; }

private:
    int     m_size;
    QString m_name;
};

class ThingManager : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<Thing*> things READ getThings NOTIFY thingsChanged)

public:
    QList<Thing*> getThings () const { return m_things; }

signals:
    void thingsChanged ();

private:
    QList<Things*> m_things;
};
于 2013-01-29T08:48:44.450 に答える
2

QQmlListPropertyを使用する最善の方法 です。この簡単なサンプルを参照してください。
オブジェクトとリストのプロパティ タイプの例

于 2015-01-21T13:38:15.690 に答える
1

によって与えられた答えeatyourgreensは正しいです。そのようにクラスを実装することで、必要な数の子孫にアクセスできます。もう 1 つ役立つヒントは、qml デリゲート要素内にモデルのエイリアスを作成することです。

ListView {
   anchors.fill: parent
   model: thing_manager.things
   delegate: ItemDelagate {}
   clip: true
   spacing: 10
}

そして、ItemDelegate.qml で、モデルのエイリアスを作成して、model.modelData を常に使用しないようにすることができます。

Item{
    width: 600
    height: 200
    property var thing: model.modelData
    Rectangle {
        anchors.fill: parent
        color: "red"
        Text {
            text: thing.name // or any other field
        }
    }
}
于 2014-12-10T12:29:46.010 に答える
0

それを達成するための非常に間接的な方法の1つは次のとおりです。

i.) qml でモデルを作成する

ListModel 
{
     id: thingModel

     ListElement 
     {
         size: 10
         name: "Apple"
     }     
}

ii.) 次に、このリストを変更するためのいくつかの JavaScript 関数を提供します。

function jAppendThing( newSize, newName )
{
    thingModel.append({"size": nameSize, "name": newName })
}

function jClearThing()
{
    thingModel.clear()
}

同様にjDeleteThingなど.

iii.) c++ から qml 関数を呼び出す方法について読むことができます

iv.) C++ リストでループを実行し、qml の追加関数を呼び出して、そのすべてのデータを qml リストにも追加します。

v.) C++ サイド リストの更新時に、上記の関数を使用して qml データを変更し、更新を維持します。

于 2013-01-11T23:14:34.730 に答える