簡體   English   中英

QML/QT 如何將對象從 C++ 轉換為 QML?

[英]QML/QT How to convert object from C++ to QML?

我花了一段時間,但最終我設法將 JavaScript/QML POJO 轉換為不是從 QObject 派生的自定義對象。

我認為通過一個工作示例更容易理解我的問題。 所以讓我們從這個開始:

struct SomeType { /* Just a plain struct that does not derive from QObject! */ }; 

SomeType FooFactory::convertQMLToSomeType(const QJSValue& val) {
  SomeType result = /*... some kind of conversion takes place here ... */
  return result;
}

void FooFactory::registerTypes(QQmlEngine& engine) {
  QMetaType::registerConverter<QJSValue, SomeType>(FooFactory::convertQMLToSomeType);
}

它的作用是注冊一個轉換器,用於將QSValue轉換為SomeType 所以現在,每當我在 QML 中做這樣的事情時

my_prop = { "foo": "some plain javascript object" };

假設my_prop在相應的 C++ 類中像這樣公開:

Q_PROPERTY(SomeType my_prop MEMBER _myProp);
SomeType _myProp;

// Somewhere else outside the class, this is needed for registering the converter
Q_DECLARE_METATYPE(SomeType);

字符串被隱式轉換為SomeType無需手動操作。

..

偉大的!

但是轉換的相反方向呢? 我需要 QML 來處理字符串,而不是QVariant(SomeType)對象(QT 在處理元系統時總是在內部使用QVariant包裝器來存儲用戶定義的類型)。

我已經嘗試過注冊這樣的逆轉換器:

QMetaType::registerConverter<SomeType, QJSValue>(FooFactory::convertBackToQML);

或這個

QMetaType::registerConverter<QVariant(SomeType), QJSValue>(FooFactory::convertBackToQML);

但這些方法都不起作用。 我相信第二行很有前途,但由於注冊靜態元類型的問題,我什至無法編譯那一行。

那么,我將如何解決這個問題? 簡短提醒一下,我無法從QObject派生SomeType ,是的,我知道這是執行此類操作的最常用方法。

有沒有人有想法? 還是我叫錯了樹? 提前謝謝了!

這可能不是您想要的,但也可能是您唯一的選擇。 您可以圍繞結構創建 QObject 包裝器類。 只需為要公開的結構中的任何值創建屬性。

class SomeWrapper : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString someData READ someData WRITE setSomeData NOTIFY someDataChanged)

public:
    explicit SomeWrapper(QObject *parent = nullptr) : QObject(parent) {}

    QString someData() { return m_struct.someData; }
    void setSomeData(QString data)
    {
        if (data != m_struct.someData)
        {
            m_struct.someData = data;
            emit someDataChanged();
        }
    }

signals:
    void someDataChanged();

private:
    SomeType m_struct;
};

如果您想像使用普通 JavaScript 對象一樣操作您的結構,那么另一個選項可能是使用QVariantMap作為您的屬性的類型。 然后,您可以在屬性的 getter 和 setter 中定義所需的轉換:

class Whichever : public QObject {
    Q_OBJECT
    Q_PROPERTY(QVariantMap my_prop READ myProp WRITE setMyProp)

    QVariantMap myProp() const {
         QVariantMap map;
         map["some_field"] = _myProp.someField;
         // Fill the other fields as needed.
         return map;
    }

    void setMyProp(const QVariantMap& map) {
        _myProp.someField = map["some_field"].toString();
        // Fill the other _myProp fields as needed.
    }
};

QVariantMap和實際 JavaScript 對象之間的轉換將由 QML 引擎自動處理。 嵌套的 JavaScript 對象也應該可以通過嵌套相應的QVariantMap s 來實現。

當然,這個選項使得屬性聲明不那么明確它對應於哪種類型,如果您需要聲明這種類型的多個屬性,可能需要更多的樣板代碼(您可以為此定義和使用自己的宏)雖然如果需要)。 但這可能是實現您所描述的最簡單方法之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM