如何设置 checked/unchecked QTableView 的多个选定行
How to set checked/unchecked multiple selected rows of a QTableView
我正在尝试应用以下 post 中概述的原则,但对于我的模型的 CheckStateRole(在我的模型的 data/setData 方法中定义):
how can i achieve to update multiple rows in a qtableview
但是,我发现 checking/unchecking 一个列(在我的例子中是第 0 列),似乎根本没有调用 commitData。
这是代码片段:
class MyTableView(QtGui.QTableView):
"""
View that will set all selected rows to the current CheckedState.
"""
def __init__(self, parent=None):
super(MyTableView, self).__init__(parent)
def commitData(self, editor):
# this method is not called when a user checks/unchecks an item
super(MyTableView, self).commitData(editor)
model = self.currentIndex().model()
current_row, current_column = self.currentIndex().row(), 0
value = model.data(model.index(current_row, current_column), QtCore.Qt.CheckStateRole)
for row in self.selectionModel().selectedRows(0):
if row != current_row:
index = model.index(row, current_column)
model.setData(index, value, QtCore.Qt.CheckStateRole)
如何使用 QAbstractTableModel 为 QTableView 中的复选框实现这一点?
在内部,checkBox 是如何处理的?调用commitData不算是delegate吗?
已解决--------------------------------
我最终通过从模型中的 setData 方法发出 CheckStateRole 的 dataChanged 来处理这个问题,然后将信号连接到将传递的索引检查状态应用于选择的方法。
出现了两个问题:
这会导致无限循环(dataChanged 调用一个方法
影响其他索引,这些索引又会发出 dataChanged ...)。这
解决方案是在设置选定索引检查时使用 blockSignals
方法中的状态。
因为 blockSignals ui 没有刷新。在内部我
假设 dataChanged 调用索引范围的视图刷新。
对视图进行简单更新即可解决此问题。
对于加载的数据模型,我不确定这是最好的方法。
我最终通过从模型中的 setData 方法发出 CheckStateRole 的 dataChanged 来处理这个问题,然后将信号连接到将传递的索引检查状态应用于选择的方法。
出现了两个问题:
- 这会导致无限循环(dataChanged 调用的方法会影响其他索引,而其他索引又会发出 dataChanged...)。解决方案是在方法中设置选定索引检查状态时 blockSignals。
- 由于 blockSignals,ui 未刷新。在内部,我假设 dataChanged 调用索引范围的视图刷新。对视图进行简单更新即可解决此问题。
对于加载的数据模型,我不确定这是最好的方法。
这是我解决它的方法(在 C++ 中)
- 将来自
TableView
的 SelectionModel
的 selectionChanged
信号连接到数据模型上的插槽:
connect(selectionModel(), &QItemSelectionModel::selectionChanged,
&model, &Model::onSelectionChanged);
- 每次选择更改时,在模型中保留一个副本。这可能看起来像这样:
void Model::onSelectionChanged(QItemSelection const& selected, QItemSelection const& deselected)
{
if (auto sm = qobject_cast<QItemSelectionModel*>(sender()))
{
mLastSelection = sm->selection();
}
}
- 在模型的
setData()
函数中,当更新以响应 CheckState
更改时,遍历整个选择以将相同的 CheckState
更改应用于所有选定的单元格。
接下来处理用户点击checkbox时TableView清除选择的问题:
从具有与 QItemSelectionModel::select
相同签名的模型发出 setSelection 信号:
Q_EMIT setSelection(mLastSelection, QItemSelectionModel::Select);
将此信号连接回选择模型,但至关重要的是,使用 QueuedConnection
执行此操作,以便它到达下一个事件循环周期。
- 在 C++ 中,要在排队连接中连接这些类型,需要使用
qRegisterMetaType
注册它们。您可以在 cpp 文件顶部的匿名命名空间中巧妙地执行此操作,如下所示:
{
bool const _ = []{
qRegisterMetaType<QItemSelection>();
qRegisterMetaType<QItemSelectionModel::SelectionFlags>();
return true;
}();
}
我正在尝试应用以下 post 中概述的原则,但对于我的模型的 CheckStateRole(在我的模型的 data/setData 方法中定义):
how can i achieve to update multiple rows in a qtableview
但是,我发现 checking/unchecking 一个列(在我的例子中是第 0 列),似乎根本没有调用 commitData。
这是代码片段:
class MyTableView(QtGui.QTableView):
"""
View that will set all selected rows to the current CheckedState.
"""
def __init__(self, parent=None):
super(MyTableView, self).__init__(parent)
def commitData(self, editor):
# this method is not called when a user checks/unchecks an item
super(MyTableView, self).commitData(editor)
model = self.currentIndex().model()
current_row, current_column = self.currentIndex().row(), 0
value = model.data(model.index(current_row, current_column), QtCore.Qt.CheckStateRole)
for row in self.selectionModel().selectedRows(0):
if row != current_row:
index = model.index(row, current_column)
model.setData(index, value, QtCore.Qt.CheckStateRole)
如何使用 QAbstractTableModel 为 QTableView 中的复选框实现这一点?
在内部,checkBox 是如何处理的?调用commitData不算是delegate吗?
已解决--------------------------------
我最终通过从模型中的 setData 方法发出 CheckStateRole 的 dataChanged 来处理这个问题,然后将信号连接到将传递的索引检查状态应用于选择的方法。
出现了两个问题:
这会导致无限循环(dataChanged 调用一个方法 影响其他索引,这些索引又会发出 dataChanged ...)。这 解决方案是在设置选定索引检查时使用 blockSignals 方法中的状态。
因为 blockSignals ui 没有刷新。在内部我 假设 dataChanged 调用索引范围的视图刷新。 对视图进行简单更新即可解决此问题。
对于加载的数据模型,我不确定这是最好的方法。
我最终通过从模型中的 setData 方法发出 CheckStateRole 的 dataChanged 来处理这个问题,然后将信号连接到将传递的索引检查状态应用于选择的方法。
出现了两个问题:
- 这会导致无限循环(dataChanged 调用的方法会影响其他索引,而其他索引又会发出 dataChanged...)。解决方案是在方法中设置选定索引检查状态时 blockSignals。
- 由于 blockSignals,ui 未刷新。在内部,我假设 dataChanged 调用索引范围的视图刷新。对视图进行简单更新即可解决此问题。 对于加载的数据模型,我不确定这是最好的方法。
这是我解决它的方法(在 C++ 中)
- 将来自
TableView
的SelectionModel
的selectionChanged
信号连接到数据模型上的插槽:
connect(selectionModel(), &QItemSelectionModel::selectionChanged,
&model, &Model::onSelectionChanged);
- 每次选择更改时,在模型中保留一个副本。这可能看起来像这样:
void Model::onSelectionChanged(QItemSelection const& selected, QItemSelection const& deselected)
{
if (auto sm = qobject_cast<QItemSelectionModel*>(sender()))
{
mLastSelection = sm->selection();
}
}
- 在模型的
setData()
函数中,当更新以响应CheckState
更改时,遍历整个选择以将相同的CheckState
更改应用于所有选定的单元格。
接下来处理用户点击checkbox时TableView清除选择的问题:
从具有与
QItemSelectionModel::select
相同签名的模型发出 setSelection 信号:Q_EMIT setSelection(mLastSelection, QItemSelectionModel::Select);
将此信号连接回选择模型,但至关重要的是,使用
QueuedConnection
执行此操作,以便它到达下一个事件循环周期。- 在 C++ 中,要在排队连接中连接这些类型,需要使用
qRegisterMetaType
注册它们。您可以在 cpp 文件顶部的匿名命名空间中巧妙地执行此操作,如下所示:
{
bool const _ = []{
qRegisterMetaType<QItemSelection>();
qRegisterMetaType<QItemSelectionModel::SelectionFlags>();
return true;
}();
}