请运行以下代码(我使用的是Qt 5.9):
QTableWidget* tableWidget = new QTableWidget(2, 2, nullptr);
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
connect(tableWidget->selectionModel(), &QItemSelectionModel::selectionChanged,
[&](const QItemSelection& selected, const QItemSelection& deselected)
{ qDebug() << "selected =" << selected << endl << "deselected =" << deselected; });
tableWidget->show();
QTimer::singleShot(10000, [=](){ tableWidget->removeRow(0); });
在10秒内,选择两行中的第一行。您将看到调试输出。它会显示您的点击选择了第0行。 然后,在10秒后,自动删除第0行。调试输出现在显示选择了第1行并取消选择了第0行。
后者对我没有任何意义。当删除第0行时,我希望之后选择“新”第0行。视觉选择的行仍然是第0行,第1行根本不存在。
自定义模型和通用视图也会发生这种情况,并通过指向不存在的行使我的应用程序崩溃。
这是理想的行为吗?我的误解在哪里?
答案 0 :(得分:0)
在删除之前更改所选行非常有意义。相反的做法可能导致读取悬空数据,例如,如果在模型更改但视图包含过期索引时刷新UI。
考虑两次删除第0行:第二次非常明显,在删除表中的最后一行之前,必须必须更改(在这种情况下取消选择)避免将无效索引作为选定行。
您可以使用以下修改示例来查看模型实际更新的时间。
import numpy as np
n = len(df)
df.loc[:,'industry'] = np.ones(n)
print(df)
解决方法强>
主要问题是,正如您在评论中指出的那样,您不能依赖信号信息:如果执行删除,那些auto tableWidget = new QTableWidget(2, 2, nullptr);
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
connect(tableWidget->selectionModel(), &QItemSelectionModel::selectionChanged,
[&](const QItemSelection& selected, const QItemSelection& deselected)
{ qDebug() << "selected =" << selected << endl << "deselected =" << deselected; });
connect(tableWidget->model(), &QAbstractItemModel::rowsRemoved, [&](const QModelIndex &, int first, int last)
{ qDebug() << "first row removed =" << first << endl << "last row removed =" << last; });
tableWidget->show();
QTimer::singleShot(10000, [=](){ tableWidget->removeRow(0); });
QTimer::singleShot(15000, [=](){ tableWidget->removeRow(0); }); // remove twice
可能有效或无效。你可以跟踪所有的变化,但这将是令人筋疲力尽的。
相反,您可以尝试延迟选择信号,因此在处理模型时,模型已更新,您可以信任选择模型中的信息。 技巧是使用计时器:处理超时事件的函数将在事件循环的下一次迭代中执行(即使超时时间为0),同时模型和窗口小部件在当前迭代中更新:
QModelIndex