QTableView :: scrollTo在模型重置后和延迟一段时间后立即

时间:2018-06-22 13:47:12

标签: c++ qt qt5

我使用QTableView和自定义模型,我想在之后滚动到特定项目 型号更新。

我创建了两个按钮“更新模型”和“滚动到”:

 btn->setText("Update model");
  QObject::connect(btn, &QPushButton::clicked, [&tbl_model, view] {
    tbl_model.update();
    auto idx = tbl_model.index(49, 0);
    qDebug() << "idx: " << idx;
    view->scrollTo(idx, QAbstractItemView::PositionAtCenter);
  });

  btn->setText("scroll to");
  QObject::connect(btn, &QPushButton::clicked, [view, &tbl_model] {
    auto idx = tbl_model.index(49, 0);
    qDebug() << "idx: " << idx;
    view->scrollTo(idx, QAbstractItemView::PositionAtCenter);
  });

更新方法代码:

  void update() {
    beginResetModel();
    auto new_size = data_.size() == 100 ? 50 : 100;
    data_.clear();
    for (int i = 0; i < new_size; ++i) {
      data_.append(i + 1);
    }
    endResetModel();
  }

如果我按“更新模型”,并且模型尺寸从50扩大到100, 然后我在窗口底部看到row == 49的项目, 然后如果我按“滚动到”按钮,我将看到它的中心。

因此,在模型完全更新后如何使用scrollTo? 当然,我可以添加processEvents或使用QTimer::singleShot, 但看起来像骇客,可能有一些事件或信号表明 查看是否可以滚动?

Full code

1 个答案:

答案 0 :(得分:2)

由于某种原因,在调用QTableView::scrollTo()之前,视图需要在重置模型(以处理某些事件)之后进入事件循环,以使后者正常工作。我记得使用Qt时曾多次遇到类似情况。

我发现使用QTimer之类的东西来安排scrollTo之后真的很不好。如果您希望使用更具可读性的解决方案,请查看this answer。基本上,您可以定义自己的QueuedInvoke函数,如下所示:

//the functor gets invoked in the thread where the contextObject lives
//or in the current thread if no contextObject is provided
template <typename Func>
void QueuedInvoke(Func&& f, QObject* contextObject = QAbstractEventDispatcher::instance()){
    QObject signalSource;
    QObject::connect(&signalSource, &QObject::destroyed, 
                     contextObject, std::forward<Func>(f), Qt::QueuedConnection);
}

在那之后,您只需将调用scrollTo的行替换为以下内容:

QueuedInvoke([view, idx]{
    view->scrollTo(idx, QAbstractItemView::PositionAtCenter);
}, view);