QTableView:dataChanged事件清除正在编辑的单元格

4
使用QTableViewQAbstractTableModel时,当模型为正在编辑的单元格发出dataChanged事件时,用户在单元格中键入但未按下回车键以“提交”编辑的字符串将被清除。
例如:单击单元格,键入“123”,单元格仍处于编辑模式等待更多文本,发出dataChanged事件并擦除“123”,留下一个空的正在编辑的单元格。
有人知道如何停止这种行为,或者模型如何检测单元格正在被编辑以防止为该单元格引发dataChanged事件吗?

我不确定,但也许是你的视图中设置了错误的EditTriggers?QAbstractItemView::CurrentChanged看起来可能会导致这种行为。 - Greenflow
在编辑时从模型中使用blocksignals,然后在完成编辑后取消信号,这样做可以吗? - Ashif
4个回答

3
我曾经遇到过同样的问题。问题在于,data() 函数被调用时使用了不同的 role 参数。当显示数据时使用 role==Qt::DisplayRole,而编辑时则使用 role==Qt::EditRole。例如,尝试更改:
QVariant MyModel::data(const QModelIndex & index, int role) const
{
  if (role == Qt::DisplayRole)
    return QString("Text to Edit");
}

to

QVariant MyModel::data(const QModelIndex & index, int role) const
{
  if (role == Qt::DisplayRole || role == Qt::EditRole)
    return QString("Text to Edit");
}

那应该就能解决问题了。

1
我遇到了同样的问题,并找到了一种不需要编写自己的委托的方法:
问题恰好如你所描述的那样:数据在后台更新,而你编辑的所有内容都被清除,因为dataChanged事件会更新所有值,从而调用数据函数,如果没有为Qt :: EditRole指定任何内容,则返回一个空的QVariant()对象。即使是Leonid的答案也会使用相同的QString("Text to Edit")覆盖您的编辑。
所以我做的是:
引入一个成员变量并定义它为可变的,这样const数据函数就可以更改它:
mutable bool m_updateData = true;

在您的后台数据更新函数中,在发出dataChanged信号之前,请检查m_update日期:
if (m_updateData)
    emit(dataChanged(index, index));

在您的数据函数中,检查编辑角色并将m_updateData设置为false:
if (role == Qt::EditRole)
{
    m_updateData = false;
}

编辑完成后,将调用setData函数,在此函数中更新您模型中的数据。在完成此操作后,请将m_updateDate重置为true。

这对我来说完美地解决了问题 :)


0

我认为你应该只在没有被编辑或仅用于Qt::ItemDataRole::DisplayRole的索引上使用dataChanged事件。 例如,要仅更新每行的第二列,请使用:

emit dataChanged(index(0, 1),
 index(rowCount() - 1, 1),
 QVector<int>{ Qt::ItemDataRole::DisplayRole });

0

请检查您的模型类,您应该在模型中重写setData方法。如果一切正确,它将在编辑数据后更新模型... 如果您有其他实现,请告诉我。

bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {
        int row = index.row();
        int col = index.column();

            //// change data

        emit(dataChanged(index, index));
        return true;
    }

    return false;
}

1
我已经完成了这个 - 这不是问题所在。问题在于,当用户正在编辑 UI 并且在调用 setData 之前,由于 dataChanged 事件 UI 刷新并擦除部分输入数据。 - Zero
你正在使用QAbstractItemDelegate吗? - Mostafa
不,我没有使用AbstractItemDelegate - Zero
不,我认为这并没有用处(除非我制作了一个最小化的代码示例),因为代码太复杂了。我认为不值得花时间的原因是,我现在相信这是Qt行为,即如果对正在编辑的单元格引发了dataChanged事件,则编辑值将重置为新数据值。我相信可以通过实现QItemDelegate来解决这个问题,它可以以任何我想要的方式处理事件,而不是依赖于Qt默认委托行为。我会更新这个QA,告诉大家我的进展情况。 - Zero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接