在 QT 中,链接模型无法按预期工作

发布于 2024-08-04 05:26:05 字数 2705 浏览 7 评论 0原文

好吧,我有一个非常基本的 QStandardItemModel,其中填充了一些数字。我设法将它显示在QTableView中,没问题。我创建了一个新模型( QAbstractItemModelQAbstractProxyModel 的子类),它是现有模型的某种层 - 需要设置源模型,并且这新图层应该对真实图层进行一些转换。

我的问题是,在顶层,说“层模型”, data( const QModelIndex & index, int role ) 成员函数从未被调用,但是我想通过以下方式更改显示方法角色参数。

下面是一个示例代码,它演示了原始模型的 data(index,role) 始终被调用,而图层模型的 data(index,role) 从不被调用。为什么? QTableView 对象如何“跳过”顶层的 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();
}

Alright, I have a really basic QStandardItemModel, filled with some numbers. I managed to display it in a QTableView, it's ok. I created a new model ( subclass either of QAbstractItemModel or QAbstractProxyModel ), which is some kind of a layer of an existing model - it is needed to set the sourcemodel, and this new layer should do some transformations on the real one.

My problem is, that in the top layer, say "layer model" the data( const QModelIndex & index, int role ) member function never called, however i would like to alter the displaying methods by the role parameter.

Here is a sample code, which demonstrates, that the original model's data(index,role) is always called, whilst the layer model's data(index,role) never. Why? How can the QTableView object "skip" the top layer's 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();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

纸短情长 2024-08-11 05:26:05

因为QTableView使用模型索引来检索数据,大概是这样的。

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

并且您将返回源模型的模型索引,而不是代理模型的索引:

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

尝试将模型索引转换为代理模型的索引

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

不要忘记重写到源的映射和从源函数的映射。


解决方案

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

Because QTableView uses the model index to retrieve the data, probably something like this.

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

And you are returning the model index of the source model instead of an index to your proxy model:

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

Try to convert the model index into an index to your proxy model

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

Don't forget to rewrite the map to source and map from source functions.


Solution

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;
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文