在 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
不同图像的字符串相同,导致 QML Image 组件无法更新,但解决方案很简单,只需在分配新像素图后删除旧像素图即可。这是实际的图像提供者:
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();
}
}
};
登记:
//in main()
engine.addImageProvider("pixmap", new PixmapProvider);
qmlRegisterType<Pixmap>("Test", 1, 0, "Pixmap");
这就是在 QML 中使用它的方式:
Pixmap {
id: pix
}
Image {
source: pix.data
}
// and then pix.load(path)
另请注意,在我的例子中,没有需要在 QML 中更新的像素图的实际修改。如果在 C++ 中更改图像,此解决方案不会自动更新 QML 中的图像,因为内存中的地址将保持不变。但解决方案同样简单 - 实施一个update()
方法分配一个new QPixmap(oldPixmap)
- 它将使用相同的内部数据,但为您提供一个具有新内存地址的新访问器,这将触发 QML 图像以更新更改。这意味着提供的访问像素图的方法将通过Pixmap
类,不是直接来自QPixmap *
因为你需要Pixmap
类来触发data
改变,所以只需添加一个访问器pix
,以防万一你做复杂或线程的事情,你可能想使用QImage
相反,并添加一个互斥体,以便底层数据在 QML 中不会更改,而在 C++ 中更改或反之亦然。