2009-09-07 7 views
5

W porządku, mam naprawdę podstawowy QStandardItemModel, wypełniony pewnymi liczbami. Udało mi się wyświetlić go w QTableView, jest w porządku. Stworzyłem nowy model (podklasę z QAbstractItemModel lub QAbstractProxyModel), który jest pewnego rodzaju warstwą istniejącego modelu - jest potrzebny do ustawienia sourcemodel, a ta nowa warstwa powinna zrobić transformacje na prawdziwym.W trybie QT modele łańcuchowe nie działają zgodnie z oczekiwaniami.

Mój problem polega na tym, że w górnej warstwie, powiedz "model warstwy", funkcja składowa data(const QModelIndex & index, int role) nigdy nie jest wywoływana, jednak chciałbym zmienić metody wyświetlania według parametru roli.

Oto przykładowy kod, który pokazuje, że oryginalny model data(index,role) jest zawsze wywoływany, podczas gdy model warstwy data(index,role) nigdy. Czemu? W jaki sposób obiekt QTableView może "pomijać" warstwę wierzchnią data(index,role)?

#include <QtGui/QApplication> 
#include <QtGui> 
#include <QStandardItemModel> 

class MyModel : public QStandardItemModel 
{ 
public: 
    MyModel(const int r, const int c, QObject* parent = 0) : QStandardItemModel(r,c,parent) {} 
    QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const { 
     qDebug() << "mymodel data"; 
     return this->itemFromIndex(index)->data(role); 
    } 
}; 

class MyProxyModel : public QAbstractProxyModel 
{ 
public: 

    MyProxyModel(QObject* parent = 0) : QAbstractProxyModel(parent) {} 
    QModelIndex index (int row, int column, const QModelIndex & parent = QModelIndex()) const { 
     return this->sourceModel()->index(row,column,parent); 
    } 
    QModelIndex parent (const QModelIndex & index) const { 
     return this->sourceModel()->parent(index); 
    } 
    QModelIndex mapFromSource (const QModelIndex & sourceIndex) const 
    { 
     return sourceIndex; 
    } 
    QModelIndex mapToSource (const QModelIndex & proxyIndex) const 
    { 
     return proxyIndex; 
    } 
    QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const { 
     qDebug() << "myproxymodel data"; 
     return this->sourceModel()->data(index,role); 
    } 

    int rowCount (const QModelIndex & parent = QModelIndex()) const { 
     return this->sourceModel()->rowCount(parent); 
    } 
    int columnCount (const QModelIndex & parent = QModelIndex()) const { 
     return this->sourceModel()->columnCount(parent); 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc,argv); 
    MyModel model(8, 2); 
    MyProxyModel mymodel; 
    mymodel.setSourceModel(&model); 

    QTableView tableView; 
    tableView.setModel(&mymodel); 

    tableView.horizontalHeader()->setStretchLastSection(true); 
    for (int row = 0; row < 8; ++row) { 
     for (int column = 0; column < 2; ++column) { 
      QModelIndex index = model.index(row, column, QModelIndex()); 
      model.setData(index, QVariant((row+1) * (column+1))); 
     } 

    } 
    tableView.show(); 
    return app.exec(); 
} 

Odpowiedz

6

Ponieważ QTableView używa indeksu modelu do pobrania danych, prawdopodobnie czegoś podobnego.

QModelIndex index = model->index(row, column, parentIndex); 
index.data(Qt::DisplayRole); 

I wracasz indeks modelu modelu źródłowego zamiast wskaźnika do modelu proxy:

QModelIndex index (int row, int column, const QModelIndex & parent = QModelIndex()) const { 
    return this->sourceModel()->index(row,column,parent); 
} 

Spróbuj przekonwertować indeks modelu w indeksie do modelu proxy

QModelIndex index (int row, int column, const QModelIndex & parent = QModelIndex()) const { 
    return this->createIndex(row,column,row); 
} 

Nie zapomnij przepisać mapy na źródło i mapować z funkcji źródłowych.


Rozwiązanie

class MyTableProxyModel : public QAbstractProxyModel 
{ 
    Q_OBJECT 
public: 
    MyTableProxyModel (QObject* parent = 0) 
     : QAbstractProxyModel(parent) { 
    } 

    QModelIndex index(int row, int column, const QModelIndex& parent=QModelIndex()) const { 
     return createIndex(row,column,row); 
    } 

    QModelIndex parent(const QModelIndex &index) const { 
     //Works only for non-tree models 
     return QModelIndex(); 
    } 

    QModelIndex mapFromSource(const QModelIndex &source) const { 
     return index(source.row(), source.column(), source.parent()); 
    } 

    QModelIndex mapToSource(const QModelIndex &proxy) const { 
     return (sourceModel()&&proxy.isValid()) 
      ? sourceModel()->index(proxy.row(), proxy.column(), proxy.parent()) 
      : QModelIndex(); 
    } 

    QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const { 
     qDebug() << "myproxymodel data"; 
     return mapToSource(index).data(role); 
    } 

    int rowCount (const QModelIndex & parent = QModelIndex()) const { 
     return sourceModel() ? sourceModel()->rowCount(parent) : 0; 
    } 

    int columnCount (const QModelIndex & parent = QModelIndex()) const { 
     return sourceModel() ? sourceModel()->columnCount(parent) : 0; 
    } 
}; 
+0

Ok, rozumiem. Mam 2 pytania: - Jak mogę osiągnąć mój cel bez tworzenia indeksów proxy? Chciałbym uniknąć tworzenia indeksów w modelu proxy, ponieważ nie będzie żadnego filtrowania/sortowania itp., A to byłoby całkowite powielenie indeksów oryginalnego modelu. - Nie widzę, jak "QSortFilterProxyModel" może mi pomóc. Muszę zakodować funkcję 'data (..)', a z tego powodu potrzebuję również kodu 'index (...)'. Co 'QSortFilterProxyModel' robi, że' QAbstractProxyModel' nie ma mojego punktu widzenia? –

+1

Należy utworzyć nowe indeksy wskazujące model proxy. QSortFilterProxyMode tworzy dla ciebie indeksy proxy. – TimW

+0

Bardzo dziękuję, mapToSource i mapFromSource były dla mnie diabelskimi oczami! To działa jak urok! –