简体   繁体   中英

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.

These are the requirements:

  • The frontend is abstract, hence the model should be applicable for Widgets as well as QML views. This comes with the restriction that the decoration role cant return QIcons (afaik).
  • The backend should be platform agnostic. On linux I useQMimeDatabase::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.

No icons, no paths. Theres only QPixmap left, right? Is this the way to go? Can I display a QPixmap from a C++ model in QML at all? 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:

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:

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:

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:

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

Example

On GitHub you can find an example I wrote for you to demonstrate the proposed solution.

Result

The example produces the following result:

带有装饰列表的程序窗口

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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