QML和C ++图像互操作性

时间:2014-12-11 17:57:58

标签: c++ image qt qml qtquick2

我查看了文档以及我在互联网上找到的任何内容,但似乎无法从C ++访问QML图像。

有办法解决这个问题吗?

1 个答案:

答案 0 :(得分:8)

可以在QtQuick1中执行,但在QtQuick2中删除了该功能。

我提出的解决方案允许在QML和C ++中使用QQuickImageProvider来生成相同的图像,该QPixmap *基本上与class Pixmap : public QObject { Q_OBJECT Q_PROPERTY(QString data READ data NOTIFY dataChanged) public: Pixmap(QObject * p = 0) : QObject(p), pix(0) {} ~Pixmap() { if (pix) delete pix; } QString data() { if (pix) return "image://pixmap/" + QString::number((qulonglong)pix); else return QString(); } public slots: void load(QString url) { QPixmap * old = 0; if (pix) old = pix; pix = new QPixmap(url); emit dataChanged(); if (old) delete old; } void clear() { if (pix) delete pix; pix = 0; emit dataChanged(); } signals: void dataChanged(); private: QPixmap * pix; }; 一起使用,后者转换为字符串,然后返回到指针类型(它确实听起来有点不安全,但已证明效果很好)。

Pixmap

data元素的实现非常简单,虽然初始有点受限,因为新的pixmap恰好分配在完全相同的内存地址class PixmapProvider : public QQuickImageProvider { public: PixmapProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) {} QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) { qulonglong d = id.toULongLong(); if (d) { QPixmap * p = reinterpret_cast<QPixmap *>(d); return *p; } else { return QPixmap(); } } }; 字符串是相同的不同的图像,导致QML图像组件不更新,但解决方案就像在分配新的pixmap之后删除旧的pixmap一样简单。这是实际的图像提供者:

//in main()
engine.addImageProvider("pixmap", new PixmapProvider);
qmlRegisterType<Pixmap>("Test", 1, 0, "Pixmap");

注册:

Pixmap {
    id: pix
}

Image {
    source: pix.data
}

// and then pix.load(path)

这就是你在QML中使用它的方式:

update()

另请注意,在我的情况下,没有实际修改需要在QML中更新的像素图。如果在C ++中更改了图像,则此解决方案不会自动更新QML中的图像,因为内存中的地址将保持不变。但是对此的解决方案同样简单 - 实现一个分配new QPixmap(oldPixmap)的{​​{1}}方法 - 它将使用相同的内部数据,但会为您提供一个带有新内存地址的新访问器,触发QML图像以更新更新。这意味着访问pixmap的提供方法将通过Pixmap类,而不是直接来自QPixmap *,因为您需要Pixmap类来触发data更改,所以只需为pix添加一个访问器,以防你做复杂或线程化的东西,你可能想要使用QImage代替并添加一个互斥锁,这样底层数据就不会在QML中被改变了用C ++或其他方式改变了。