如何设置 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 来处理这个问题,然后将信号连接到将传递的索引检查状态应用于选择的方法。

出现了两个问题:

对于加载的数据模型,我不确定这是最好的方法。

我最终通过从模型中的 setData 方法发出 CheckStateRole 的 dataChanged 来处理这个问题,然后将信号连接到将传递的索引检查状态应用于选择的方法。

出现了两个问题:

  • 这会导致无限循环(dataChanged 调用的方法会影响其他索引,而其他索引又会发出 dataChanged...)。解决方案是在方法中设置选定索引检查状态时 blockSignals。
  • 由于 blockSignals,ui 未刷新。在内部,我假设 dataChanged 调用索引范围的视图刷新。对视图进行简单更新即可解决此问题。 对于加载的数据模型,我不确定这是最好的方法。

这是我解决它的方法(在 C++ 中)

  • 将来自 TableViewSelectionModelselectionChanged 信号连接到数据模型上的插槽:
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;
    }();
}