如何彻底改变 QAbstractTableModel 的底层数据?

How to change underlying data of QAbstractTableModel completely?

这是我第一次post来这里,但自从我开始编程以来,我得到了你们所有人的很多帮助。

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

我首先将后台事物(数据存储等)与 GUI 分开。 现在我有一个模板 class Matrix 并且我写了一个模板 class MatrixModel 继承自 QAbstractTableModel。这工作正常,意味着我可以编辑 table 并在视图和模型数据中刷新值。

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

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 会怎样?它会影响模型的数据吗?我尝试了很多东西,但没有任何效果。一个 "problem" 是我不能使用标准 signal/slot 语法,因为我正在使用模板 classes.

我最后一次尝试是在模型中进行更新 class:

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 希望你能帮助我。如果您需要更多信息,请询问^^

此致

丹尼斯

编辑 1:好的,到目前为止我想通了(在你的帮助下 :)),我必须在模型中再次编写矩阵的函数(例如 transpose())并从那里发出数据变化(用发出 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: 也许数据存储有问题,所以这是我的复制构造函数和我的矩阵的私有变量 class:

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 的所有编辑都应通过模型中的函数完成。这意味着您的模型将有一个 public transpose 函数,该函数在您的 matrix 数据上调用 transpose 然后发出 dataChanged() 信号。而且你不应该直接访问你的 matrix 因为在模型不知情的情况下改变它不会给你想要的东西。这样,在每次更改 matrix 变量后调用 updateAll 就不是您的责任,因为您的模型进行了更改并相应地更新了自身。 . .

我明白了...

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

有效...模型已经是一个指针,所以我将相同的指针指向 lambda 函数。现在我只需要弄清楚我的转置函数有什么不对,因为它仍然无法正常工作,但崩溃已经消失了:P谢谢你的建议:)