我有一个带有自定义模型的列表视图。该模型允许我将文本添加到列表的底部(使用'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));
}
这似乎有效,但我仍然坚持自动滚动。
答案 0 :(得分:0)
我做了一个类似队列的表模型实现。我认为QAbstractItemModel
类似。最好的方法是使用QQueue
来存储数据。
现在,这是QAbstractTableModel
的剪辑(它是QAbstractItemModel
的子类,所以它应该有用; mEvents
是QQueue
):
// 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)
答案 1 :(得分:0)
这是我目前的做法,似乎效果很好:
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似乎可行。
如果已经存在,我还添加了自动“滚动到底部”(即,视图要么固定在特定项目上,要么在最后滚动到底部时粘贴到最新项目。)