数据更改时自动刷新QTableView

piw*_*iwi 7 c++ model-view-controller qt

我编写了一个自定义数据模型,用几个QTableViews显示.

从技术上讲,一切正常:我的观点显示了我的模型所做的更改.我的数据模型是可编辑的,并且该setData()方法确实发出dataChanged()信号并true在成功编辑时返回.

但是,我的问题是我必须将鼠标移到a QTableView上以显示实际的更改,而我希望所有视图在制作时显示更改,而不需要与视图交互以使它们成为更新.

任何的想法?谢谢,


可能有必要提一下,我不使用默认Qt::EditRole角色来编辑数据,而是使用自定义枚举值(命名ActiveRole).

这是我正在寻找的:我的数据模型包含有关如何显示数据的属性,用于生成馈送到viewS的样式表.

因此,当改变模型时,对于每个视图,其所有项都受到影响,这dataChanged()就是发送信号的原因,其中索引覆盖所有单元.

我也尝试发射layoutChanged(),但它似乎没有改变我的情况下的行为.

以下是该setData()方法的摘录:

bool DataModel::setData(QModelIndex const& idx, QVariant const& value, int role)
{
  if (ActiveRole == role)
  {
    // Update data...

    QModelIndex topLeft = index(0, 0);
    QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1);

    emit dataChanged(topLeft, bottomRight);
    emit layoutChanged();

    return true;
  }
  return false;
}
Run Code Online (Sandbox Code Playgroud)

以下是该data()方法的示例:

QVariant DataModel::data(QModelIndex const& idx, int role) const
{
  if (ActiveRole == role)
  {
    boost::uuids::uuid id;

    return qVariantFromValue(id);
  }

  return QVariant();
}
Run Code Online (Sandbox Code Playgroud)

并且flags()确实表明了一个可编辑的模型:

Qt::ItemFlags DataModel::flags(QModelIndex const& idx) const
{
  if (false == idx.isValid())
  {
    return Qt::ItemIsEditable;
  }

  return QAbstractTableModel::flags(idx) | Qt::ItemIsEditable;
}
Run Code Online (Sandbox Code Playgroud)

我有一个自定义委托,它严重依赖于这个SO线程来覆盖paintsizeHint方法以绘制一个QTextDocument.此外,它提供的内容ActiveRole在编辑器setEditorData,并呼吁DataMode::setDatasetModelData:

void DataModelDelegate::setEditorData(QWidget* editor, QModelIndex const& idx) const
{
  auto active = qVariantValue<boost::uuids::uuid>(idx.data(ActiveRole));
  static_cast<DataModelEditor*>(editor)->setActive(active);
}

void DataModelDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, QModelIndex const& idx) const
{
  auto active = static_cast<DataModelEditor*>(editor)->getActive();
  model->setData(idx, qVariantFromValue(active), ActiveRole);
}
Run Code Online (Sandbox Code Playgroud)

createEditor(),我将编辑器中的信号插入我的委托的插槽中以提交数据:

QWidget* DataModelDelegate::createEditor(QWidget* parent, QStyleOptionViewItem const& option, QModelIndex const& idx) const
{
  auto editor = new DataModelEditor(parent);
  connect(editor, SIGNAL(activeItem()), this, SLOT(commitEditorData()));
  return editor;
}
Run Code Online (Sandbox Code Playgroud)

单击某个项目时,编辑器会触发该activeItem信号; 连接的插槽commitEditorData依次commitData通过参数中的编辑器提升信号.

所以我的所有视图都使用这些自定义委托,编辑器和数据模型.我正在与之交互的视图会立即显示更改,但其他视图需要将鼠标悬停在它们上方以显示更改.

piw*_*iwi 7

我实际上发现了问题,那就是我的其他视图没有被正确通知数据更改:我的每个视图都显示了我的数据的不同部分,所以其他视图需要被通知dataChanged(),但是对于他们自己的,正确的索引.

另外,在我的Qt应用程序不是窗口管理器中的活动窗口时,我也遇到了更新视图的问题.解决方案是调用repaint()主窗口.

  • 该解决方案(调用“repaint()”)对我不起作用。此外,IMO,答案并不完整。应描述或举例说明如何在代码中使用“dataChanged()”以达到预期效果。 (3认同)

S.C*_*hao 5

我遇到了同样的问题,请允许我在piwi的答案中添加详细的说明。如果更改数据以及更新单列或多列(或行,具体取决于您的要求)的内容,则应发出一组从左上到右下的索引。例如,如果您有一个如下表:

在此处输入图片说明

并且,现在您已经更改了一些数据,并且想要更新单元格第1行第1-2列,那么您应该发出信号dataChange

emit datachange(index(1,1),index(1,2));
Run Code Online (Sandbox Code Playgroud)

  • 我怎样才能从模型外部做到这一点?也就是说,没有“QModelIndex”? (2认同)