2011-01-27 19 views
7

Model dizinlerinde verileri işlemek için kesinlikle ihtiyaç duyduğum bir işaretçi içeren bir QAbstractListModel hazırladım. Öyle gibi verileri ekleyin:QModelIndex yeni bir sırayla nasıl ilişkilendirilir?

void PointListModel::addPoint(int frameNumber, QPoint const& pos) 
{ 
    PointItem *pointItem = new PointItem(frameNumber, pos); 
    QModelIndex newRow = this->createIndex(m_points.count(), 0, pointItem); 

    qDebug() << newRow.internalPointer(); 

    beginInsertRows(newRow, m_points.count(), m_points.count()); 
    m_points.insert(m_points.count(), pointItem); 
    endInsertRows(); 

    emit pointAdded(pointItem, pos); 
} 

Sadece sonra ben beginInsertRows argüman yeni satıra değil, yeni satırın gerçek model endeksi arasında ebeveyn modeli endeksi istiyor fark olmasıydı. Bu noktada, bu noktada, bu özel satırla ilişkilendirmek için bana QModelIndex tedarik etmenin bir yolunu vermedim. Bu yeni satır için kendi model dizinimi nasıl oluşturabilirim?

cevap

6

Tamam, bazı araştırmalarımın yanlış anladığımı öğrendikten sonra cevabımı yeniden yazdım.

Yeni veriler eklediğinizde yeni bir dizin oluşturmak için özel bir şey yapmamalısınız.

PointItem *pointItem = new PointItem(frameNumber, pos); 
// assume you insert a top level row, having no parent 
beginInsertRows(QModelIndex(), m_points.count(), m_points.count()); 
m_points.insert(m_points.count(), pointItem); 
endInsertRows(); 

Sonra talep ve bazı endeksinin üst belirleyecek parent() yöntemine endeksler yaratacak index() yöntemini uygulamak gerekir, ancak bir liste modele sahip olduğundan, olması gerektiği: You kod aşağıdaki gibi görünmelidir muhtemelen her zaman QModelIndex()'u iade et. İşte a good article about creating custom models.

Burada çalışan QAbstractListModel tam bir örnektir:

class MyModel: public QAbstractListModel { 
    Q_OBJECT 
    public: 
    virtual QModelIndex index(int row, int column = 0, 
     const QModelIndex &parent = QModelIndex()) const; 
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; 
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 
    void add(int i); 
    private: 
    QList<int> list; 
}; 

void MyModel::add(int i) 
{ 
    beginInsertRows(QModelIndex(), list.size(), list.size()); 
    list.append(i); 
    endInsertRows(); 
} 

QModelIndex MyModel::index(int row, int column, 
     const QModelIndex &parent) const 
{ 
    return hasIndex(row, column, parent) ? createIndex(row, column, (void*)&list[row]) 
    : QModelIndex(); 
} 

int MyModel::rowCount(const QModelIndex &parent) const 
{ 
    if (parent.isValid()) 
    return 0; 
    return list.size(); 
} 

QVariant MyModel::data(const QModelIndex &index, 
    int role) const 
{ 
    if (!index.isValid()) 
    return QVariant(); 
    if (role != Qt::DisplayRole) 
    return QVariant(); 
    return QVariant(QString::number(*static_cast<int*>(index.internalPointer()))); 
} 
+0

ama anladığım kadarıyla, index() işlevi sadece yeni satırların oluşturulması için çağrılmaz. Yeni bir satır ile var olan arasındaki dizin() çağrısını nasıl ayırt edebilirim? Verilerimi depolayan bir QMap var, ancak QMap anahtarı gitmiyor Şu anda satır numarasına göre –

+0

@nessup, varsayılan QAbstractListModel :: index() uygulaması her zaman geçerli koordinatlar için createIndex() öğesini çağırır, bu yüzden her çağrı için yeni bir dizin oluşturması gerekiyor sanırım, bu bana da garip gelse de M aybe dizin oluşturma işlemi ucuz olarak kabul edilir, bu yüzden birden fazla çift dizin oluşturmak için mükemmeldir. Ne de olsa, uygulamanızın varsayılan değeriyle aynı olacaktır, tek fark, veri işaretçisi olarak NULL yerine createIndex() için anlamlı bir şey iletmenizdir (varsayılan uygulamada olduğu gibi). –

+0

Tamam, teşekkürler. Kodumda bir QMap tutmaya ve QMap belirli bir satırda uygun QModelIndex içermiyorsa yeni bir QModelIndex döndürmeye çalışacağım. Nasıl geçtiği konusunda size geri döneceğim. –

2

Ben pişirdim bir olan modeli indeksleri kesinlikle verilerin işlenmesi için gerekli bir işaretçi ihtiva QAbstractListModel. Yanlış gereklerine başlarsanız

, yanlış çözümlere :)

modeli QModelIndex 'ın row() benzersiz tanımlamak daha fazlasına ihtiyacımız kalmaması yeterince basit bir liste ile bitirmek veri dizin adresleri. Daha önce

PointItem * item = static_cast<PointItem*>(mi.internalPointer()); 

ne zaman

Yani, plm sizin PointListModel nerede yerine

PointItem * item = plm->pointItemFromIndex(mi); 

yapabilir bir QModelIndexmi verilen. Eğer PointItem erişmeniz gerektiğinde ortalıkta buna bir işaretçi yoksa, bunu şöyle tekrar oluşturabilir:

PointItem * PointListMode::pointItemFromindex(const QModelIndex &mi) const { 
    return mi.isValid() ? m_points[mi.row()] : 0 ; 
} 
:

PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model()); 
// check for !plm here (!mi.isValid() || qobject_cast fails) 

Buna karşılık, PointListMode::pointItemFromIndex() fiili çalışma yapacağını

Bu, QT'deki QAbstractListModel ile çalışırken fark edilmesi gereken en önemli şeydir: int row ile zihinsel olarak QModelIndex'u değiştirin, sahip olduğu her şeyi yoksayın (geçersiz bir QModelIndex, row() == -1 içeriyor).

QAbstractTableModel için de geçerlidir: QModelIndex değerini int row, int column'a göre azaltın. Her şeyi unut.

ihtiyacınız sadece zaman QModelIndex (dahil olmak üzere tam onun internalPointer() veya internalId() bir ağaç modeli (QAbstractItemModel) uygulamaya ne zaman olacağı.

o ne istiyorum daha yakın gidiyor gibi bu görünüyor
İlgili konular