c++ - 如何在 Qt5 中使用带有模型/ View /委托(delegate)的自定义小部件?

标签 c++ qt qt5 qtwidgets

在我目前使用的专有代码库中,有一个自定义 ListView (派生形式 QListView )。
当前,当大量项目(> 10000)使主线程卡住时,它会出现问题。
View 中的每个项目都是在 QtDesigner 中设计的自定义小部件。
为了渲染每一行,我们使用 setIndexWidget ,在 QAbstractItemModel::rowsInserted 上调用信号。对于每个插入的行,来自 firstlast为每个索引设置了自定义小部件。
我尝试移植此代码以使用 QStyledItemDelegate ,因为将项目小部件与实际模型断开连接似乎可以解决渲染缓慢的问题。
在这种情况下,Qt5 可以按需懒惰地渲染 View 中的项目。在显示列表之前,我们不需要为 View 创建每个小部件。
我使用派生自 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);
    }
这对于静态内容来说已经足够了,但是我的小部件有复选框并且可以被选中。
我真的不明白如何使它具有交互性,同时保留代表提供的好处(按需渲染等)。
我的问题是如何让委托(delegate)处理用户事件?就像鼠标点击一样,选择会发生变化。
涵盖委托(delegate)的 Qt5 示例太简单了,我不明白如何使用委托(delegate)绘制自定义小部件。

最佳答案

我尝试使用的最佳解决方法是在静态渲染 QPixmap 之间进行动态切换。当鼠标移动或委托(delegate)接收事件时,真正的小部件。
首先我覆盖QAbstractItemDelegate::editorEvent ,因此当委托(delegate)接收到任何事件时,它会切换到该 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);
}
在我看来,我还启用了所有描述的打开编辑器的方式。
this->setEditTriggers(QAbstractItemView::EditTrigger::AllEditTriggers);
this->setMouseTracking(true);
connect(this, &MyView::entered, this, &MyView::openPersistentEditor);
QAbstractItemView::entered当鼠标悬停在小部件上时会发出信号。
从用户的角度来看,没有任何变化,在他们可以与列表项交互之前,它已经被真实的小部件动态替换。
一些垃圾收集策略似乎也是必要的,因为如果用户将鼠标悬停在许多小部件上,即使他们很长时间没有与之交互,它们也会保留在内存中。对于已删除的行,编辑器会自动销毁,但这可能还不够。
基于开源 Qt5 的软件(Telegram Desktop)在不使用小部件的情况下呈现大列表。他们手动渲染列表,覆盖 QWidget::paint方法和实现虚拟化(仅绘制屏幕上看到的内容)。

关于c++ - 如何在 Qt5 中使用带有模型/ View /委托(delegate)的自定义小部件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63481521/

相关文章:

c++ - Q_GADGET 可以是其他 Q_GADGET 的属性吗?

c++ - 如何用c/c++读写 "Excel"(智能手机APP开发)

c++ - 指向成员变量的多态指针

c++ - 使用 OpenCV、Boost 线程和多个摄像头

javascript - YouTube嵌入-播放/暂停播放

c++ - Qt析构函数调用关闭的小部件

c++ - 如何在 `make uninstall` 期间从 QT5 中的 qmake 运行自定义命令?

c++ - 如何使用 C++ new 而不是 C malloc 分配内存

c++ - Qt/C++ - 设置禁用按钮的背景?

c++ - 如何配置Qt Creator来编译qupzilla?