2016-09-14 5 views
1

Как я могу вернуть подклассу QObject из QAbstractListModel и использовать его в QML ListView.возвращает пользовательский подкласс QObject из QAbstractListModel и использует его в ListView

Я попытался вернуть объекты в качестве роли отображения, и я использую в своем qml display.property для доступа к свойствам, он отлично работает, но я видел на некоторых сообщениях людей, использующих модель как qobject из qml, и доступ к свойствам как model.property , Я что-то упускаю?.

Другой вопрос: если я хочу выставить объект на уровне 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, где подробный вид не является частью делегата master view, это очень сложно сделать. –

+1

Сложно посоветовать без дальнейших подробностей. Вы можете иметь карту где-нибудь с Notes и ID. Когда вы затем укажете ID как пользовательский, вы можете просто найти заметку на карте по id. – Hayt

ответ

2

Поскольку вы уже ответили на ваш второй вопрос, дайте мне взять на себя первый, т.е. display.propertyName против model.propertyName

В основном первый один только короткая рука для model.display.propertyName, то есть свойство «отображения» из данных модели по данному индексу. В вашем случае, который возвращает объект, который имеет свойства при включении.

model.propertyName также может быть записан как propertyName, что означает, что метод data() модели называется «роль», являющимся числовым эквивалентом для «propertyName».

Это сопоставление от «propertyName» к его числовому эквиваленту выполняется с помощью метода QAbstractItemModel::roleNames(). Его реализация по умолчанию имеет некоторые базовые сопоставления, такие как отображение «отображение» на Qt::DisplayRole.

+0

Если я понимаю вас правильно, model.property эквивалентен для model.data (index, roleNames() ["property"]) ?? –

+0

Немного нравится, да. Имя свойства присваивается целочисленному значению роли через хэш, возвращаемый функцией roleNames(). Это целочисленное значение затем передается в качестве второго аргумента в data() –

+0

ok спасибо за объяснение, что меня сбивало с толку - это модель в делетете, которая фактически представляет модель model.at (index), но модель отверстия. –

0

я играл немного с qml ListView, пытаясь выяснить, как вывести текущие данные в внешний мир. Так мне удалось это сделать, может быть, это будет полезно для новичков вроде меня.

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 
    } 
} 

Как вы можете видеть в коде, чтобы выставить данные CurrentItem я только объявить свойства в делегатом пункте (свойство имени типа строки в данном примере), а затем связать свойство на ListView (selectedName в этом примере) в currentItem.property, таким образом свойство в ListView будет автоматически обновляться при выборе других элементов из списка, и у меня будет доступ к этой форме элементов других элементов пользовательского интерфейса.