我有一个QTableWidget
,其中使用表小部件的QHeaderView
示例启用了拖放:m_tableWidget->verticalHeader()->setSectionsMovable(true);
另外,我已经实现了一个撤销机制。现在,我想实现一个拖放操作可以使用撤销机制来撤销。
对于这个撤销机制,我需要在拖放之前和之后保存数据。假设我有一个方法来存储旧数据,这现在并不重要。
为了存储新数据并将其压入撤消堆栈,我连接到QHeaderView
的sectionMoved
信号:connect(m_tableWidget->verticalHeader(), &QHeaderView::sectionMoved, this, &MyTableWidget::dragAndDrop);
然后调用的函数基本上如下所示:
void
MyTableWidget::dragAndDrop(int logicalIndex, int oldVisualIndex, int newVisualIndex)
{
// Get the table data which is stored in a vector
auto& tableData = oldVector;
// Synchronize to reflect the drag & drop change
auto synchronizedTableData = synchronize(oldVisualIndex, newVisualIndex);
// Push on the undo stack
m_undoStack->push(new Undo(synchronizedTableData, oldTableData));
}
最后,撤消堆栈中的函数基本上如下所示:
void
Undo::redo()
{
tableWidget->setRowCount(synchronizedTableData.size());
// Apply the synchronized vector data to the table
for (int i = 0; i < synchronizedTableData.size(); ++i) {
for (int j = 0; j < synchronizedTableData.at(i).size(); ++j) {
m_tableWidget->setItem(i, j, new QTableWidgetItem(synchronizedTableData.at(i).at(j).toString()));
}
}
}
}
然而,整个方法有一个重大缺陷:当然,使用垂直标题的拖放操作只会更改视图,而模型本身不会更新。因此,基本上,如果我遍历表格并显示其内容,我仍然会按照拖放操作之前的方式排列项目。现在,如果表格按照undo stack函数中所示进行设置,则视图会被破坏,如下图所示:
如果要将第二行拖动到最后一行之前,则应如下所示:
但是,它看起来像这样:
这看起来就像拖放实际上已经执行了两次:123456 -〉134526 -〉145236。然而,有趣的是,如果我再一次迭代表,数据已经被正确地更改了。所以现在,模型是完整的,但是视图没有被正确地更新。
现在,我猜想我混淆了视图和垂直标题模型之间的某些东西。因此,我的想法是,我可以通过在拖放一行后更新标题后面的模型来解决这个问题。或者,我必须在撤消堆栈中成功更新模型后重新更新视图。
但我不知道如何实现。我仍然不知道到底是什么在标题被调用两次,使视图被改变两次。也许整个方法本身是有缺陷的?任何想法将不胜感激。
先谢了!
1条答案
按热度按时间u3r8eeie1#
所以,我找到了第一个解决方案。然而,它只是作为某种变通办法。
新的想法是,我可以保存头状态并恢复它。
所以基本上,每次我想通过拖放来重新排列标题项时,我必须按下这样一个项。我可以用它来存储旧的标题状态。然后,在拖放之后,我可以做以下事情:
现在,我在拖放操作后手动恢复这个状态,这当然容易出错,但至少可以防止拖放操作重复。
但是,它本身并没有回答问题。因此,我不会将其标记为答案。但如果其他人可能遇到这个问题,这可能会帮助您。