QML和C++图像互操作性

3

我已经查阅了文档以及在互联网上找到的所有信息,但似乎无法从C++中访问QML图像。

是否有解决办法?

1个回答

8

在QtQuick1中是可能实现的,但是这个功能在QtQuick2中已被移除。

我想到的解决方案是通过实现一个QQuickImageProvider来在QML和C++中使用相同的图像。这个提供者基本上使用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元素的实现非常简单,尽管初始时有一些限制,因为新的pixmap恰好被分配到与不同图像的data字符串相同的内存地址上,导致QML Image组件无法更新,但解决方案很简单,只需在新pixmap分配后删除旧的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();
        }
    }
};

注册:

//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中不需要对pixmap进行实际修改来更新。如果在C++中更改了图像,因为内存中的地址将保持不变,所以此解决方案将不会自动更新QML中的图像。但是,解决此问题同样很简单——实现一个update()方法,分配一个new QPixmap(oldPixmap),它将使用相同的内部数据但为其提供一个新的访问器和一个新的内存地址,这将在更改时触发QML图像更新。这意味着访问pixmap的推荐方法将是通过Pixmap类,而不是直接从QPixmap *,因为你需要Pixmap类来触发data更改,因此只需添加一个pix访问器。如果你做复杂或多线程的操作,你可能需要使用QImage并添加一个互斥锁,以使底层数据在C++中被更改或者在QML中被更改时不会被同时更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接