Inl*_*ine 6 c++ qt qt5 qtwidgets
在我当前使用的专有代码库中,有一个自定义列表视图(派生形式QListView)。
目前,当大量项目(> 10000)导致主线程冻结时,会出现问题。视图中的每个项目都是在 QtDesigner 中设计的自定义小部件。
为了渲染每一行,我们使用setIndexWidget,它在QAbstractItemModel::rowsInserted信号上调用。对于每个插入的行,为每个索引设置从first到自定义小部件。last
我尝试将此代码移植到 use QStyledItemDelegate,因为从实际模型中断开项目小部件似乎可以解决渲染缓慢的问题。
在这种情况下,Qt5 可以根据需要延迟渲染视图中的项目。在显示列表之前,我们不需要创建每个用于查看的小部件。
我使用派生自QStyledItemDelegate. 我在构造函数中创建一个列表项小部件,然后像这样覆盖绘制事件。
void paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const override {
auto baseWid = getBaseWidget(); // Get's list item widget pointer
setSubEditorData(baseWid,index); // Set's it's state to display current item
baseWid->resize(option.rect.size());
QPixmap pixmap(option.rect.size());
baseWid->render(&pixmap);
painter->drawPixmap(option.rect, pixmap);
}
Run Code Online (Sandbox Code Playgroud)
这对于静态内容来说已经足够了,但是我的小部件有复选框并且可以选择。
我真的不明白如何使其具有交互性,同时保留代表提供的好处(按需渲染等)。
我的问题是如何让委托处理用户事件?就像鼠标点击一样,选择也会发生变化。
涵盖委托的 Qt5 示例太简单了,我不明白如何使用委托绘制自定义小部件。
我尝试使用的最佳解决方法涉及QPixmap当鼠标移动或委托接收事件时在静态渲染和真实小部件之间进行动态切换。
首先,我重写QAbstractItemDelegate::editorEvent,因此当委托收到任何事件时,它会切换到真正的小部件QModelIndex。
切换到真实的小部件是使用 完成的QAbstractItemView::openPersistentEditor。之后QAbstractItemDelegate::createEditor会自动调用该调用来获取小部件。
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
{
auto view = qobject_cast<NyView*>(parent());
view->openPersistentEditor(index);
return Base::editorEvent(event, model, option, index);
}
Run Code Online (Sandbox Code Playgroud)
在我看来,我还启用了所有描述的打开编辑器的方式。
this->setEditTriggers(QAbstractItemView::EditTrigger::AllEditTriggers);
this->setMouseTracking(true);
connect(this, &MyView::entered, this, &MyView::openPersistentEditor);
Run Code Online (Sandbox Code Playgroud)
QAbstractItemView::entered当鼠标悬停在小部件上时会发出信号。
从用户的角度来看,没有任何变化,在他们可以与列表项交互之前,它已经动态地替换为真正的小部件。
一些垃圾收集策略似乎也是必要的,因为如果用户将鼠标悬停在许多小部件上,即使他们很长时间没有与其交互,它们也会保留在内存中。对于已删除的行,编辑器会自动销毁,但这可能还不够。
基于 Qt5 的开源软件(Telegram Desktop)无需使用小部件即可呈现大型列表。他们手动渲染列表覆盖QWidget::paint方法并实现虚拟化(仅绘制屏幕上看到的内容)。