2016-09-14 8 views
1

QAbstractListModelからカスタムQObjectサブクラスを返してQML ListViewで使用するにはどうすればよいですか?QAbstractListModelからカスタムQObjectサブクラスを返してListViewで使用する

オブジェクトを表示役割として返そうとしましたが、プロパティにアクセスするためにqml display.propertyを使用しましたが、うまくいきましたが、qmlのqobjectとしてmodelを使用し、model.property 。私は何かを逃していますか?

もう1つの質問:オブジェクトをListViewレベルで公開し、それを使ってマスタービューの詳細のような他のパネルを設定すると、デリゲートのバリアントプロパティとしてロールが表示されますonCurrentItemChanged信号でリストビューレベルに設定するのは正しい方法ですか?

これは私がしようとしていますが、それは動作しないものです:

#ifndef NOTE_H 
#define NOTE_H 

#include <QObject> 

class Note : public QObject 
{ 
    Q_OBJECT 

    Q_PROPERTY(QString note READ note WRITE setNote NOTIFY noteChanged) 
    Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) 

    QString m_note; 
    int m_id; 

public: 
    explicit Note(QObject *parent = 0); 
    Note(QString note, int id, QObject *parent = 0); 

    QString note() const 
    { 
     return m_note; 
    } 

    int id() const 
    { 
     return m_id; 
    } 

signals: 

    void noteChanged(QString note); 

    void idChanged(int id); 

public slots: 
    void setNote(QString note) 
    { 
     if (m_note == note) 
      return; 

     m_note = note; 
     emit noteChanged(note); 
    } 
    void setId(int id) 
    { 
     if (m_id == id) 
      return; 

     m_id = id; 
     emit idChanged(id); 
    } 
}; 

#endif // NOTE_H 

ビューモデル:ビューモデルの

#ifndef NOTESVIEWMODEL_H 
#define NOTESVIEWMODEL_H 

#include <QAbstractListModel> 
#include <QVector> 
#include "note.h" 

class NotesViewModel : public QAbstractListModel 
{ 
    Q_OBJECT 

    QVector<Note*> notes; 


public: 
    NotesViewModel(); 

    QVariant data(const QModelIndex &index, int role) const override; 
    int rowCount(const QModelIndex &parent) const override; 

}; 

#endif // NOTESVIEWMODEL_H 

が実装:

NotesViewModel::NotesViewModel() 
{ 
    notes.append(new Note("note 1", 1)); 
    notes.append(new Note("note 2", 2)); 
    notes.append(new Note("note 3", 3)); 
    notes.append(new Note("note 4", 4)); 
    notes.append(new Note("note 5", 5)); 
} 

QVariant NotesViewModel::data(const QModelIndex &index, int role) const 
{ 
    qDebug() << "fetching data : " << index.row(); 
    if(!index.isValid()) return QVariant(); 
    if(index.row() >= 5) return QVariant(); 
    if(role == Qt::DisplayRole) 
     return QVariant::fromValue(notes[index.row()]); 
    return QVariant(); 
} 

int NotesViewModel::rowCount(const QModelIndex &parent) const 
{ 
    Q_UNUSED(parent) 
    return notes.count(); 
} 
+1

一般に、モデルは内部オブジェクトを公開するのではなく、表示ロールなどのようなものだけを表示できますが、カスタムロールを追加してデータ(QVariant)を使って返すこともできます。識別子のように、オブジェクトを別の場所に取得します。 – Hayt

+0

あなたが言っていることは正しいと私はあなたに同意しますが、詳細ビューがマスタービューの代理人の一部ではないmasterdetailビューのような状況では、それは非常に難しいです。 –

+1

それ以上の詳細なしで助言するのは一種難しいです。ノートとIDのどこかに地図を置くことができます。 IDをカスタムとして返すと、IDでマップにメモを配置できます。 – Hayt

答えて

2

すでにあなたの2番目の質問に答えたので、私は最初の1でみましょう、すなわちdisplay.propertyName

model.propertyName対基本的に最初のものはの「表示」プロパティすなわち、 model.display.propertyNameためだけの短い手であります指定されたインデックスのモデルのデータにアクセスしています。あなたの場合は、その上にプロパティを持つオブジェクトを返します。

model.propertyNameもちょうどpropertyNameと書くことができます。つまり、モデルのdata()メソッドが呼び出され、 "role"が "propertyName"の数値に相当します。

"propertyName"から数値に相当する数値へのこのマッピングはQAbstractItemModel::roleNames()メソッドで行われます。 デフォルトの実装には、 "display"をQt::DisplayRoleにマッピングするなどの基本マッピングがあります。

+0

私があなたを正しく理解していれば、model.propertyはmodel.data(index、roleNames()["property"])と同等ですか? –

+0

そうですね、そうです。 「プロパティ」名は、roleNames()によって返されたハッシュを通じて整数のロール値にマップされます。 その整数値が2番目の引数としてdata() –

+0

に渡されました。説明に感謝しましたが、実際にはmodel.at(インデックス)を表すデリゲートのモデルが穴モデルです。 –

0

私が演じほとんどの場合、qml ListViewでcurrentItemデータを外部に公開する方法を理解しようとしています。これは私がそれをやり遂げた方法です、多分私のような初心者のために使用されるでしょう。

import QtQuick 2.7 
import QtQuick.Controls 2.0 
import QtQuick.Layouts 1.0 

ApplicationWindow { 
    visible: true 
    width: 640 
    height: 480 
    title: qsTr("Hello World") 

    ListModel { 
     id: modell 
     ListElement { 
      fname: "houssem" 
      age: 26 
     } 
     ListElement { 
      fname: "Anna" 
      age: 26 
     } 
     ListElement { 
      fname: "Nicole" 
      age: 26 
     } 
     ListElement { 
      fname: "Adam" 
      age: 27 
     } 
    } 

    ListView { 
     id: lv 
     height: 100 
     width: 200 
     clip: true 
     model: modell 
     property string selectedName: currentItem.name 
     delegate: Component { 
      Item { 
       id: mainItem 
       width: ListView.view.width 
       height: 80 
       property string name: fname 
       Text { 
        text: "name " + fname + " age " + age 
       } 
       MouseArea { 
        anchors.fill: parent 
        onClicked: mainItem.ListView.view.currentIndex = index 
       } 
      } 
     } 
    } 
    Text { 
     anchors.right: parent.right 
     text: lv.selectedName 
    } 
} 

あなたは、私はちょうど(本例では、文字列型のnameプロパティ)デリゲートのアイテムのプロパティを宣言しなければならなかったのCurrentItemのデータを公開して、リストビューのプロパティをバインドするために、コード内で見ることができるように

(この例ではselectedName)をcurrentItem.propertyに追加すると、ListViewのプロパティはリストから他のアイテムを選択すると自動的に更新され、UIの他のアイテムからこのアイテムへのアクセスが可能になります。

関連する問題