2017-01-12 4 views
0

QT 5.7、QML、およびC++を試してみるための簡単なプロジェクトを進めています。私はいくつかのボタンを使って項目を追加したり削除したりできる項目のリストを持つ簡単なインターフェースを作りたいと思っています。私は一緒に何かを一緒にしようとしているオンラインの別のガイドを読んできましたが、私は立ち往生し続けています。私はQQmlListProperty<T>QAbstractListModelを使用してみましたが、私は両方のアプローチについて質問があります:私のプロジェクトのためにQML/QTのC++リストからの項目の追加と削除5.7

  1. QQmlListProperty<T>を使用する権利のことですか私はQAbstractListModelを使用する必要がありますか?
  2. いずれの場合も、QMLビューにリストが変更されたことを通知するにはどうすればよいですか?
  3. 私は 'QAbstractListModel'を使用すると、リストに項目を追加したり削除したりする方法をQ_INVOKABLEだけ作成する必要がありますか?

以下は、QQmlListProperty<T>QAbstractListModelの両方のコードです。私はこのポストを短く保つためにクラスの実装の大部分を省いていますが、実装が必要な場合は追加することができます。 getItms()

QQmlListPropertyアイテムクラス

class PlaylistItemModel : public QObject 
{ 
     Q_OBJECT 
     Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged) 
    public: 
     explicit PlaylistItemModel(QObject *parent = 0); 
     QString getName(); 
     void setName(const QString &name); 

    signals: 
     void nameChanged(); 

    public slots: 

    private: 
     QString _name; 
}; 

QQmlListProperty Listクラス

class PlaylistModel : public QObject 
{ 
     Q_OBJECT 
     Q_PROPERTY(QQmlListProperty<PlaylistItemModel> items READ getItems NOTIFY itemsChanged) 
    public: 
     explicit PlaylistModel(QObject *parent = 0); 
     QQmlListProperty<PlaylistItemModel> getItems() const; 
     Q_INVOKABLE void addItem(PlaylistItemModel *item); 
     Q_INVOKABLE void removeItem(PlaylistItemModel *item); 
     Q_INVOKABLE void clearItems(); 

     static void append(QQmlListProperty<PlaylistItemModel> *list, PlaylistItemModel *item); 
     static PlaylistItemModel* at(QQmlListProperty<PlaylistItemModel> *list, int index); 
     static int count(QQmlListProperty<PlaylistItemModel> *list); 
     static void clear(QQmlListProperty<PlaylistItemModel> *list); 

    signals: 
     void itemsChanged(); 

    public slots: 

    private: 
     QList<PlaylistItemModel*> _items; 
}; 

実装:

QQmlListProperty<PlaylistItemModel> PlaylistModel::getItems() const 
{ 
    return QQmlListProperty<PlaylistItemModel>(this, _items, &append, &count, &at, &clear); 
} 

QAbstractListModel

class MyModel : public QAbstractListModel 
{ 
    Q_OBJECT 
    public: 
     enum ModelRoles 
     { 
      ItemRole = Qt::UserRole + 1 
     }; 

     MyModel(QObject *parent = 0); 

     // QAbstractItemModel interface 
     int rowCount(const QModelIndex &parent) const; 
     QVariant data(const QModelIndex &index, int role) const; 
     QHash<int, QByteArray> roleNames() const; 

    private: 
     QList<QString> _listData; 
     QString itemAt(const QModelIndex &index) const; 
}; 

答えて

4

は、私は一般的にQAbstractListModelはあなたが唯一の単純なリストで作業することがあります確信している場合を除き、ほとんどの時間で行く権利クラスであることを示唆しています。

いずれの場合も、QMLビューにリストが変更されたことを通知するにはどうすればよいですか?

(QAbstractListModelが継承)QAbstractItemModelは、あなたが何かが起こったこと、それに接続されているビュー(複数可)を知らせるために、あなたのサブクラスから呼び出す必要があり、多数の異なる方法があります。アイテムを挿入するときは、QAbstractItemModel::beginInsertRowsQAbstractItemModel::endInsertRowsが必要です。

あなたのモデルはシンプルなものを表現している場合、インスタンスの名前のリストのように、あなたの挿入は、次のようになります。

はと仮定:

class MyModel : public QAbstractListModel 
{ 
public: 
    Q_INVOKABLE void addPerson(const QString &name); 
private: 
    QVector<QString> m_names; 
}; 

void MyModel::addPerson(const QString &name) 
{ 
    beginInsertRows(QModelIndex(), m_names.count(), m_names.count()); 
    m_names.append(name); 
    endInsertRows(); 
} 

をあなたが、その後QAbstractItemModel::rowCountQAbstractItemModel::roleNamesを実装する必要があり、そしてQAbstractItemModel::dataは最低限必要ですが、あなたがすでに処理しているようです。データの編集を実装する場合は、QAbstractListModel::setDataも実装します。

あなたはそれをやった後は、(qmlRegisterType使用)タイプの登録:&をインポートし

qmlRegisterType<MyModel>("MyModelImport", 1, 0, "MyModel"); 

とをQMLからそれをインスタンス化し、あなたのビューでそれを使用します。

import MyModelImport 1.0 
import QtQuick 2.6 

ListView { 
    id: listView 
    anchors.fill: parent 
    model: MyModel { 
    } 
    delegate: TextInput { 
     text: model.text 
     onEditingFinished: { 
      // when the text is edited, save it back to the model (which will invoke the saveData we overloaded) 
      model.text = text 
     } 
    } 

    Rectangle { 
     height: 100 
     width: 400 
     color: "red" 
     Text { 
      text: "Add item" 
     } 
     MouseArea { 
      anchors.fill: parent 
      onClicked: listView.model.addName("Some new name") 
     } 
    } 
} 
+0

はありがとうそんなに、それはすごく見え、多くのものをクリアします。 1つの質問: 'MyModel'が' QObjects'のリストを持っていたら(私の質問では 'PlaylistItemModel'に似ています)、どちらのクラスでも何が変わるのでしょうか? –

+0

いいえ、多かれ少なかれ同じように機能します。あなたはQVector を持っていて、あなたのデータ関数にはそれらのプロパティにアクセスします。 –

+0

あなたのアイテムが 'QObject'ベースの場合、モデルはQObjectポインタを1つの単一のロールとして返し、QMLのオブジェクトのプロパティにアクセスできます。しかし、エントリごとに複数のデータ値を持つためのQObjectベースのデータエントリは必要ありません。モデルは内部データ構造でそれを行うことができます。 –

関連する問題