【问题标题】:QTableView::scrollTo immediately after model reset and after some delayQTableView::scrollTo 在模型重置后并经过一些延迟后立即
【发布时间】:2018-06-22 23:47:02
【问题描述】:

我使用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

【问题讨论】:

    标签: c++ qt qt5


    【解决方案1】:

    由于某种原因,在调用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);
    

    【讨论】:

    • 感谢您的回答,但我发现奇怪的事情,如果我在“更新模型”按钮处理程序中连续两次调用 scrollTo 都按预期工作,scrollTo 在内部使用 processEvent,或者.. ?
    • @user1244932,这真的很奇怪(我在这里也有同样的行为)。你的解释很中肯。我快速浏览了QAbstractItemView::scrollTo 的源代码,但找不到罪魁祸首。也许你有更好的眼睛;)无论如何,我不会考虑调用scrollTo两次作为解决方案......
    猜你喜欢
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多