2014-03-28 4 views
11

QML에서 QAbstractListModel 파생 모델을 사용하고 싶습니다. 뷰에 모델 바인딩은 이미 효과적입니다.QAbstractListModel 파생 모델의 get 메소드와 같이 QML ListModel을 구현하는 방법

내가 달성하고자 다음 일은 가능하다 같은 QML의 ListModel

grid.model.get(index).DisplayRole 

으로 특정 항목과 자신의 역할에 액세스 할 수있는 능력이다 그러나 나는 어떻게 QAbstractListModel 파생 내에서이 get 메소드를 구현하는 아무 생각이 없다 모델.

힌트가 있습니까?

답변

18

당신은이 같은 QAbstractItemModel 파생 클래스에 Q_INVOKABLE 기능을 추가 할 수 있습니다 : 내 사용자 정의 모델을 사용하여

여기 예를 들어 목록보기 완성도를 들어

... 

Q_INVOKABLE QVariantMap get(int row); 

... 

QVariantMap get(int row) { 
    QHash<int,QByteArray> names = roleNames(); 
    QHashIterator<int, QByteArray> i(names); 
    QVariantMap res; 
    while (i.hasNext()) { 
     i.next(); 
     QModelIndex idx = index(row, 0); 
     QVariant data = idx.data(i.key()); 
     res[i.value()] = data; 
     //cout << i.key() << ": " << i.value() << endl; 
    } 
    return res; 
} 

이 너무 { "bookTitle" : QVariant("Bible"), "year" : QVariant(-2000) }처럼 뭔가를 반환합니다 .bookTitle을 사용할 수 있습니다.

+1

성능 향상을 위해'QModelIndex idx = index (row, 0);'를 루프 밖으로 이동시킬 수 있습니다. –

0

내 접근 방식은 객체의 속성을 QML에 직접 노출하는 것입니다. 여기에 그 구현 - https://stackoverflow.com/a/14424517/1059494

+0

개체의 속성이 어떻게 노출되는지 실제로 알 수 없습니다. Q_PROPERTIES 매크로를 어딘가에 보지 않아도 될까요? – avb

+0

전체 개체를 노출합니다. 그런 다음 JS는 Q_PROPERTY 매크로로 선언 된 특정 속성을 조회 할 수 있습니다. –

11

당신이 C + + 측면에서 특별한 일을하지 않아도 목록 모델에서 역할에 대한 고전적인 접근 방식을 사용하려면 항상 같은 모델을 가지고 있으며 데이터 메소드를 구현해야합니다 :

QVariant QAbstractItemModel::data(const QModelIndex & index, int role = Qt::DisplayRole) const 

model 연결된 속성이 ListView에 위임 사용할 수 있습니다 QML에서 서로 다른 역할에 액세스하려면 : 그 어디서든 Qt는 문서에 설명되어 생각하지 않는다

model.display // model.data(index, Qt::DisplayRole) in c++ 
model.decoration // Qt::DecorationRole 
model.edit // Qt::EditRole 
model.toolTip // Qt::ToolTipRole 
// ... same for the other roles 

(아직) ,하지만 찾을 수 QML 양식에 액세스 할 수있는 속성을 디버그 모드로 시작하고 대리점에 중단 점을 넣거나 모든 속성을 콘솔에 인쇄하십시오. 대리자 내의 model 속성은 QQmlDMAbstractItemModelData 유형이므로 일부 백그라운드에서 "Qt magic"이 발생하고 목록 모델 데이터를 감싸는 래퍼처럼 보입니다. Qt 설명서에서 공식적인 내용을 찾을 수 없었습니다. QML 디버거 등으로 혼자서 알아 냈습니다.)

델리게이트 외부에서 모델 데이터에 액세스해야하는 경우 기능에 대한 빌드가 있다고 생각하지 않으므로 직접 수행해야합니다.

나는 count 속성과 기본에 get α- 함수와 유사한 QML의 ListModel 노출하는 사용자 정의 QAbstractListModel 클래스의 예를 들어했다 :

mylistmodel.h을

class MyListModel : public QAbstractListModel 
{ 
    Q_OBJECT 
    Q_PROPERTY(int count READ rowCount NOTIFY countChanged) 

public: 
    explicit MyListModel(QObject *parent = 0); 

    int rowCount(const QModelIndex & = QModelIndex()) const override { return m_data.count(); } 
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 

    Q_INVOKABLE int get(int index) const { return m_data.at(index); } 

signals: 
    void countChanged(int c); 

private: 
    QList<int> m_data; 
}; 

mylistmodel.cpp

MyListModel::MyListModel(QObject *parent) : 
    QAbstractListModel(parent) 
{ 
    m_data << 1 << 2 << 3 << 4 << 5; // test data 
    emit countChanged(rowCount()); 
} 

QVariant MyListModel::data(const QModelIndex &index, int role) const 
{ 
    if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) 
     return QVariant(); 

    int val = m_data.at(index.row()); 

    switch (role) { 
    case Qt::DisplayRole: 
     return QString("data = %1").arg(val); 
     break; 
    case Qt::DecorationRole: 
     return QColor(val & 0x1 ? Qt::red : Qt::green); 
     break; 
    case Qt::EditRole: 
     return QString::number(val); 
     break; 
    default: 
     return QVariant(); 
    } 
} 

속성과 함수를 QML에 노출하는 것이 매우 쉽기 때문에 이것을 위해 좋은 방법이라고 생각합니다.

ListView { 
    anchors.fill: parent 
    model: MyListModel { id: myModel } 
    delegate: Text { 
     text: model.display 
    } 

    Component.onCompleted: { 
     console.log(myModel.count) // 5 
     console.log(myModel.get(0)) // 1 
    } 
} 
+2

특정 인덱스의 항목과 JS 함수의 특정 역할에 액세스하려고합니다. 예 : 'myString = grid.model.get (3) .DisplayRole'. 나는 당신의 대답이 내가 이것을 성취하는 데 어떻게 도움이 될지 모르겠습니다. – avb

+0

당신이 대의원의 내부에 있다면 내 대답은 더 일반적이었다. 외부에서 특정 인덱스에 액세스하는 것은 드물지만 'myString = grid.model.get (3) .display' (DisplayRole이 아닌)를 시도한 것과 같은 방식으로 작동해야합니다. 작동하지 않으면 동일한 방식으로 반복 할 수 있습니다 모델 데이터의 모든 속성은 문서화되어 있지 않기 때문에 사용할 수있는 속성을 확인할 수 있습니다 (예를 들어 앱 없이는 할 수 없습니다). – Xander

+1

'myString = grid.model.get (3) .display'가 어떻게 작동합니까? QAbstractListModel에는 get이라는 메서드가 없습니다. 그래서 저는 그것을 직접 구현해야합니다. 그리고 그것은 질문입니다. 어떻게이 방법을 구현해야합니까? – avb

-1

Stac에서 많은 잘못된 해결책이 있기 때문에 이것은 매우 오랜 시간이 걸렸습니다. koverflow.내가 여기에 응답을 게시 한

는 :

How to access ListView's current item from qml

이 QAbstractItemModel에서 파생 된 또는 QML에 직접 내장, 심지어 트리 모양의 모델에 액세스 할 수 있는지, 모든 모델에 적용됩니다.

0

이렇게하는 또 다른 방법은 QAbstractItemModel의 내장 함수를 직접 사용하는 것입니다. via

grid.model.data(grid.model.index(index, 0), 0 /*== Qt::DisplayRole*/) 

이것은 기술적으로 작동하지만 사용자가 지정하는 문자열 대신 역할에 대한 숫자 코드를 알아야합니다. 여기서 가장 큰 문제는 roleNames()을 결정하는 기본 제공 기능 만 있다는 것입니다. 이름 문자열을 적절한 숫자 값으로 매핑하려면 반전 함수를 구현하고 Q_INVOKABLE을 사용하여 노출 시키거나 QML에서 roleNames()의 결과 인 QHash을 수동으로 처리해야합니다.