【问题标题】:QListView: how to automatically scroll the view and keep current selection on correct items in view when removing items from the topQListView:从顶部删除项目时如何自动滚动视图并在视图中保持当前选择的正确项目
【发布时间】:2015-12-12 06:26:02
【问题描述】:

我有一个带有自定义模型的列表视图。该模型允许我将文本添加到列表底部(使用'addText(const QString&)')并从列表顶部删除项目(使用'removeItemsFromTop(int _iCount)')。

向视图添加文本并将模型大小保持在某个最大值以下(比如说“MAX_LIST_SIZE”),同时始终保持视图(即当前选择和视图中的项目在删除项目时不应该改变)的最佳方法是什么)。

解决方案最好是一个我可以在任何我使用我的自定义模型的地方使用的函数。

我查看了 QListView 上的 indexAt(...)、scrollTo(...)、currentIndex(...) 和 setCurrentIndex(...) 方法,但我不知道如何将所有这个在一起。

到目前为止,我有(用于自动滚动视图)

// add items here ...

// cleanup
QModelIndex indexViewTop = listView->indexAt(QPoint(8, 8));
if (listModel->rowCount() > MAX_SIZE)
{
    int iRemoveCount = (listModel->rowCount() - MAX_SIZE) + MAX_SIZE/10;
    listModel->clearTextFromFront(iRemoveCount);
    listView->scrollTo(indexViewTop.sibling(indexViewTop.row() - iRemoveCount, 0), QAbstractItemView::PositionAtTop);
}

这应该在删除项目时滚动列表视图以保持视图一致,但 indexAt(...) 总是返回无效索引。

为了保持选择一致,我尝试了:

// add items her ...

// cleanup
if (listModel->rowCount() > MAX_SIZE)
{
  int iCurrentViewIndex = listView->currentIndex().row();
  int iRemoveCount = (listModel->rowCount() - MAX_SIZE) + MAX_SIZE/10;
  listModel->clearTextFromFront(iRemoveCount);
  listView->setCurrentIndex(listModel->index(iCurrentViewIndex - iRemoveCount, 0));
}

这似乎可行,但我仍然卡在自动滚动上。

【问题讨论】:

    标签: c++ qt


    【解决方案1】:

    我做了一个类似队列的表模型实现。我认为QAbstractItemModel 是类似的。最好的方法是使用QQueue 来存储数据。

    现在,这是 QAbstractTableModel 的片段(它是 QAbstractItemModel 的子类,所以它应该可以工作;mEventsQQueue):

    // custom table for inserting events
    void EventPreviewTableModel::insertEvent(const DeviceEvent &event) {
        beginInsertRows(QModelIndex(), 0, 0);
        mEvents.enqueue(event);
        endInsertRows();
    
        if (mEvents.size() > SIZE) {
          beginRemoveRows(QModelIndex(), mEvents.size(), mEvents.size());
          mEvents.dequeue();
          endRemoveRows();
        }
    }
    

    并且还覆盖data()rowCount() 以提供正确的数据。

    对于第二部分,使用ItemIsSelected 标记您要选择的项目是通过:Qt::ItemFlags QAbstractItemModel::flags(const QModelIndex & index)

    【讨论】:

    • 你会用什么来保持视图中的可见项目(即自动滚动以保持视图固定)?
    • @ArnoDuvenhage 它们将使用data() 函数自动检索,即override 接收QModelIndex,因此来自QQueue 的数据将被返回(从QQueue 中删除的数据看起来被删除)。
    • 我用我迄今为止尝试过的方法扩展了我的答案。希望它有助于显示我被困在哪里。该模型本身似乎有效。
    【解决方案2】:

    这是我目前的方法,似乎效果很好:

    void addTitlesToList(Model *model, QListView *view, std::vector<Object*> &items)
    {
        QScrollBar *pVerticalScrollBar = view->verticalScrollBar();
        bool bScrolledToBottom = pVerticalScrollBar->value() == pVerticalScrollBar->maximum();
        QModelIndex indexViewTop = view->indexAt(QPoint(8, 8));
    
        // add to model
        model->pushItems(items);
    
        // cleanup if model gets too big
        if (model->rowCount() > model->maxListSize())
        {
            int iCurrentViewIndex = view->currentIndex().row();
            int iRemoveCount = (int)(model->rowCount() - model->maxListSize()) + (int)model->maxListSize()/10;
            model->removeItemsFromFront(iRemoveCount);
    
            // scrolls to maintain view on items
            if (bScrolledToBottom == false)
            {
                _pView->scrollTo(indexViewTop.sibling(indexViewTop.row() - iRemoveCount, 0), QAbstractItemView::PositionAtTop);
            }
    
            // maintain selection
            if (iCurrentViewIndex >= iRemoveCount)
            {
                view->setCurrentIndex(_pModel->index(iCurrentViewIndex - iRemoveCount, 0));
            }
            else
            {
                view->setCurrentIndex(QModelIndex());
            }
        }
    
        // move scroll bar to keep new items in view (if scrolled to the bottom)
        if (bScrolledToBottom == true)
        {
            view->scrollToBottom();
        }
    }
    

    indexAt(QPoint(...)) 遇到的一个问题是我在将项目添加到列表后调用它,这似乎导致它总是返回无效索引。在将任何内容添加到模型之前调用 indexAt 似乎有效。 如果已经存在,我还添加了自动“滚动到底部”(即,如果一直滚动到底部,视图要么固定在特定项目上,要么坚持到最新项目)。

    【讨论】:

      猜你喜欢
      • 2020-07-06
      • 2016-12-12
      • 2020-09-11
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多