如何完全更改QAbstractTableModel的底层数据

How to change underlying data of QAbstractTableModel completely?

本文关键字:数据 QAbstractTableModel 何完全      更新时间:2023-10-16

这是我在这里的第一篇文章,但自从我开始编程以来,我收到了你们所有人的很多帮助。

我是Qt的新手,目前正在努力制作我的第一个项目。我的问题是关于模型、底层数据和视图之间的通信。

我首先将后台的东西(数据存储等)与GUI分离。现在我有了一个模板类Matrix,并编写了一个继承自QAbstractTableModel的模板类MatrixModel。这很好,意味着我可以编辑表,并且在视图和模型中的数据中刷新值。

现在我的问题是:如何在不编写新方法的情况下更改模型中的数据?

mainwindow.cpp:

matrix<int> m = {{1,2,3},{4,5,6},{7,8,9}};
MatrixModel<int>* model = new MatrixModel<int>(m);
QTableView* tableView = new QTableView;
tableView->setModel(model);

有什么方法可以对模型的底层数据调用m.transpose()吗?如果我更改m会发生什么?它会影响模型的数据吗?我尝试了很多方法,但都没用。一个"问题"是我不能使用标准的signal/slot语法,因为我使用的是模板类。

我最后一次尝试是在模型中创建一个更新类:

template<typename T>
void MatrixModel<T>::updateAll() {
    QModelIndex topLeft = index(0,0);
    QModelIndex bottomRight = index(rowCount()-1, columnCount()-1);
    emit dataChanged(topLeft, bottomRight);
}

我试着用一个按钮和一个lambda函数连接它:

connect(transposeButton, &QPushButton::clicked, [=,&m,&model]() {
m.transpose(); model->updateAll();
});

但如果我按下按钮,我的程序似乎会崩溃。我真的很失望xD希望你能帮助我。如果你需要更多信息,请直接询问^^

致以最诚挚的问候

Dennis

第1版:好吧,到目前为止,我已经明白了(在你的帮助下:),我必须在模型中再次编写矩阵的函数(例如transpose()),并从那里发出数据更改(使用emit-dataChanged或beginResetModel()…)但我无法修改数据背后的模型。如果我写

这个在主窗口:

connect(transposeButton, &QPushButton::clicked, [&model]() {
    model->transpose();
});

这在模型中:

template<typename T>
void MatrixModel<T>::transpose() {
    m(0,0) = 5;
}

如果我按下转置按钮,我的程序就会崩溃。如果我评论行

m(0,0) = 5;

一切正常。

编辑2:也许数据存储有问题,所以这里是我的复制构造函数和矩阵类的私有变量:

private:
std::vector <T> data;
size_t rows, columns;
//Copy constructor
template<typename T>
matrix<T>::matrix(const matrix<T>& other)
    : rows(other.rows), columns(other.columns) {
    data = other.data;
}

您应该将matrix变量作为模型中的私有成员,这样对matrix的所有编辑都应该通过模型中的函数来完成。这意味着您的模型将具有一个公共transpose函数,该函数在matrix数据上调用transpose,然后发出dataChanged()信号。你不应该直接访问你的matrix,因为在模型不知情的情况下更改它不会得到你想要的。这样,您就没有责任在每次更改matrix变量后调用updateAll,因为您的模型进行了更改并相应地更新了自己。

我拿到了…

connect(transposeButton, &QPushButton::clicked, [model]() {
    beginResetModel();
    m(0,0)=50;
    endResetModel();
});

工作。。。模型已经是一个指针,所以我给lambda函数提供了相同的指针。现在我只需要弄清楚我的转置函数有什么不对劲,因为它仍然不起作用,但崩溃已经消失了:P谢谢你的建议:)