简体   繁体   English

如何将 QPixmap 从 C++ 模型传递到 QML?

[英]How to pass QPixmap from a C++ model to QML?

I use QAbstractItemModel to provide icons for all sorts of things in the context of a keyboard launcher.我使用 QAbstractItemModel 在键盘启动器的上下文中为各种事物提供图标。

These are the requirements:这些是要求:

  • The frontend is abstract, hence the model should be applicable for Widgets as well as QML views.前端是抽象的,因此该模型应该适用于 Widgets 以及 QML 视图。 This comes with the restriction that the decoration role cant return QIcons (afaik).这伴随着装饰角色不能返回 QIcons (afaik) 的限制。
  • The backend should be platform agnostic.后端应该与平台无关。 On linux I useQMimeDatabase::mimeTypeForFile > QMimeType::iconName > QIcon::fromTheme .在 linux 上,我使用QMimeDatabase::mimeTypeForFile > QMimeType::iconName > QIcon::fromTheme On macOS Qt does not provide such facilities, therefore I plan to use icon(for:) which returns NSImage , which I would have to draw into a QPixmap.在 macOS Qt 上不提供这样的设施,因此我计划使用icon(for:)返回NSImage ,我必须将其绘制到 QPixmap 中。

No icons, no paths.没有图标,没有路径。 Theres only QPixmap left, right?只剩下 QPixmap 了吧? Is this the way to go?这是要走的路吗? Can I display a QPixmap from a C++ model in QML at all?我可以在 QML 中显示来自 C++ 模型的 QPixmap 吗? Or should I cache the icon on disk and pass a path in the model?或者我应该在磁盘上缓存图标并在模型中传递路径?

Another requirement is that this should be reasonably fast since its a keyboard launcher and results should show up instantly.另一个要求是这应该相当快,因为​​它是一个键盘启动器,结果应该立即显示出来。

Solution解决方案

I must admit, it is not as straightforward as I wish it were, but here it is anyway:我必须承认,它并不像我希望的那么简单,但无论如何都是这样:

Provide the model from the C++ backend, eg:从 C++ 后端提供模型,例如:

class Backend : public QObject
{
    ...
    QStandardItemModel *model() const { return m_model; }
    ...

private:
    QStandardItemModel *m_model;
};

Use a QQuickImageProvider subclass to get the pixmap of the decoration role for the given model index like that:使用QQuickImageProvider子类获取给定模型索引的装饰角色的像素图,如下所示:

QPixmap requestPixmap(const QString &id, QSize *, const QSize &) override {
    const QModelIndex &index(m_model->index(id.toInt(), 0));
    const QIcon &icon(m_model->data(index, Qt::DecorationRole).value<QIcon>());

    return icon.pixmap(QSize(16, 16));
}

In main.cpp you need the following code:main.cpp您需要以下代码:

Backend backend;

engine.rootContext()->setContextProperty("backend", &backend);
engine.addImageProvider(QLatin1String("icons"), new PixmapBuilder(backend.model()));

qmlRegisterUncreatableType<QStandardItemModel>("QStandardItemModel", 1, 0, "QStandardItemModel", "The model should be created in C++");

Finally set the sourse of the Image component in QML like that:最后像这样在 QML 中设置Image组件的源:

Image {
    id: name
    source: "image://icons/" + index
}

Example例子

On GitHub you can find an example I wrote for you to demonstrate the proposed solution.在 GitHub 上,您可以找到我为您编写的示例来演示建议的解决方案。

Result结果

The example produces the following result:该示例产生以下结果:

带有装饰列表的程序窗口

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM