【问题标题】:QTableView: dataChanged event clears cell being editedQTableView:dataChanged 事件清除正在编辑的单元格
【发布时间】:2013-08-28 12:29:40
【问题描述】:

使用QTableViewQAbstractTableModel - 当模型为正在编辑的单元格发出dataChanged 事件时,用户在单元格中键入的字符串(但未按下回车键以“提交”编辑)被删除了。

示例:单击一个单元格,输入“123”,单元格仍处于编辑模式等待更多文本,发出dataChanged 并删除“123”,留下一个空单元格编辑模式。

有谁知道如何阻止这种行为,或者模型如何检测单元格何时被编辑以防止为该单元格引发 dataChanged 事件?

【问题讨论】:

  • 我不确定,但您的视图中设置的 EditTriggers 可能是错误的? QAbstractItemView::CurrentChanged 看起来可能会导致这种行为。
  • 在编辑时可以使用模型中的块信号吗?并在您完成编辑后取消阻止信号?。

标签: qt qtableview


【解决方案1】:

检查您的模型类,您应该覆盖模型中的 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;
}

【讨论】:

  • 我已经做到了——这不是问题所在。问题在于,当用户正在编辑 UI 并且在调用 setData 之前,UI 会由于 dataChanged 事件而刷新并擦除部分输入的数据。
  • 你在使用 QAbstractItemDelegate 吗?
  • 不,我没有使用AbstractItemDelegate
  • 不 - 我认为这没有用(除非我制作了 SSCE),因为代码太复杂了。我认为不值得花时间的原因是我现在相信这是 Qt 行为,如果为正在编辑的单元格引发 dataChanged 事件,则编辑值将重置为新数据值。我相信这可以通过实现一个 QItemDelegate 来解决,它可以以我想要的任何方式处理事件,而不是依赖于 Qt 默认委托行为行为。我会用我的进度更新这个 QA。
【解决方案2】:

我遇到了同样的问题。问题是,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");
}

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

这应该可以解决问题

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,并找到了一种方法,而无需编写自己的 Delegate:

    问题正是您所描述的:数据在后台更新,您编辑的所有内容都被清除,因为 dataChanged 事件会更新所有值,从而调用 data 函数,如果没有,则返回一个空的 QVariant() 对象为 Qt::EditRole 指定。即使是 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。

    这对我来说非常适合:)

    【讨论】:

      【解决方案4】:

      我认为您应该仅将dataChanged 事件用于未编辑的索引或仅用于Qt::ItemDataRole::DisplayRole。 例如。为每一行使用更新第二列:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        • 2012-12-20
        • 1970-01-01
        • 2016-07-10
        相关资源
        最近更新 更多