如何彻底改变 QAbstractTableModel 的底层数据?
Posted
技术标签:
【中文标题】如何彻底改变 QAbstractTableModel 的底层数据?【英文标题】:How to change underlying data of QAbstractTableModel completely? 【发布时间】:2016-05-13 18:31:05 【问题描述】:这是我在这里的第一篇文章,但是自从我开始编程以来,我得到了你们所有人的很多帮助。
我是 Qt 新手,目前正在尝试制作我的第一个项目。我的问题是关于模型、底层数据和视图之间的通信。
我首先将后台内容(数据存储等)与 GUI 分开。
现在我有一个模板类Matrix
,我写了一个模板类MatrixModel
,它继承自QAbstractTableModel
。这工作正常,意味着我可以在视图和模型数据中编辑表格和刷新值。
现在我的问题是:如何在不编写新方法的情况下更改模型中的数据?
主窗口.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
会怎样?它会影响模型的数据吗?我尝试了很多东西,但没有任何效果。一个“问题”是我不能使用标准的信号/槽语法,因为我正在使用模板类。
我最后一次尝试是在模型中创建一个更新类:
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: 可能是数据存储有问题,所以这里是我的复制构造函数和我的矩阵类的私有变量:
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;
【问题讨论】:
如果您的模型尺寸发生变化,dataChanged()
信号是不够的。您应该在更改数据之前调用beginResetModel()
,然后在完成后调用endResetModel()
。 . .
因此,如果您的矩阵不是平方矩阵,则调用 transpose()
然后仅发出 dataChanged()
信号可能会导致崩溃并访问矩阵中的无效索引
好的,我明白了,但我可以从我的模型中调用它。但是我从我的 mainwindow.cpp 调用函数 m.transpose() ,我无法调用 beginResetModel (因为它受到保护)。而且我不想在我的矩阵模型中再次编写所有函数。
除此之外,我正在尝试使用方形来减少我必须注意的问题。但你猜一件事。如果我发出 layoutChanged 会发生什么?不是要重新排列维度吗?
【参考方案1】:
您应该将 matrix
变量作为模型中的私有成员,以便对 matrix
的所有编辑都应通过模型中的函数完成。这意味着您的模型将有一个公共的transpose
函数,该函数在您的matrix
数据上调用transpose
,然后发出dataChanged()
信号。而且您不应该直接访问您的matrix
,因为在模型不知情的情况下更改它不会提供您想要的。这样,在每次更改 matrix
变量后调用 updateAll
不是您的责任,因为您的模型进行了更改并相应地更新了自身。 . .
【讨论】:
好吧,只是这么想:P 所以我必须为我的模型重写函数。但是我读到我们不应该使用resetmodel,因为它会再次绘制所有内容。从左上到右下发射不是更好吗?除此之外,如果我尝试调用模型函数(即使是简单的函数,例如我 beginResetModel transpose endResetModel 的新转置函数。谢谢您的帮助:) 我发现,删除 beginResetModel() 和 endResetModel() 是可行的。所以在模型中编辑 m 是有效的。 如果你的模型的尺寸没有改变,发出dataChanged()
就足够了,但是如果你的尺寸正在改变,你应该调用像beginRemoveRow
或beginResetModel
这样的函数,或者..然后@ 987654333@或endRemoveRow
...改变数据结构后
对不起....不是我把它注释掉了 xD 也许连接语句有问题?
它只是崩溃了。如果我从连接 lambda 函数调用模型函数,似乎就是这种情况【参考方案2】:
我明白了……
connect(transposeButton, &QPushButton::clicked, [model]()
beginResetModel();
m(0,0)=50;
endResetModel();
);
works...模型已经是一个指针,所以我将相同的指针指向 lambda 函数。现在我只需要弄清楚我的转置功能有什么问题,因为这仍然无法正常工作,但是崩溃已经消失了:P 谢谢你的建议 :)
【讨论】:
以上是关于如何彻底改变 QAbstractTableModel 的底层数据?的主要内容,如果未能解决你的问题,请参考以下文章
linuxio_uring 和 eBPF 将如何彻底改变 Linux 中的编程
数字经济之父TED演讲:区块链将如何彻底改变我们的经济?(附视频&演讲稿)
听~英语数字经济之父TED演讲:区块链将如何彻底改变我们的经济?(附视频&演讲稿)