2016-04-08 4 views
2

Es gibt ein Modell von QAbstractListModel geerbt, ich verwende es in qml. Eine der Eigenschaften dieses Modells sind Parameter, die für den Elementtyp dieses Modells spezifisch sind. Das ist ein Element die Parameter dieser Klasse TemperatureParam, DifrentParamType ein anderes, ein drittes noch etwas ... Wie kann ich ein Objekt an qml übergeben und sicher sein, dass der Speicher nach der Verwendung freigegeben ist? Der Code unten funktioniert jetzt wie ich es brauche, aber es scheint mir, dass es nicht sicher ist.Senden Sie ein Objekt von C++ an qml. Was ist mit freiem Speicher?

Param-Klasse ist so trivial:

class QuickTemperatureParam : public QObject 
{ 
    Q_OBJECT 
    Q_PROPERTY(float param1 READ param1 WRITE setParam1) 
//... 
}; 

Modellklasse (Hier ist, was ich frage):

class SectionsModel : public QAbstractListModel 
{ 
//... 
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override 
{ 
//... 
    int type = getType(idx); 
    if (type == 1) 
    { 
     auto p = new QuickTemperatureParam(idx); 
     p->deleteLater(); // This is all right or no? 
     return qVariantFromValue(p); 
    } 
    else if (type == 2) 
    //... 
} 
}; 

QML etwas wie folgt aus:

ListView { 
    model: sectionsModel 

    delegate: Rectangle { 
     color: model.statusColor 

     ItemDelegate { 
      text: model.title 
      highlighted: ListView.isCurrentItem 

      onPressed: 
       switch (model.type) 
       { 
       case SectionType.Temperature: 
        temperatureParam.openItem(model) 
        break; 
       case SectionType.Lighting: 
        lightingParam.open(model) 
        break; 
       } 
     } 
    } 
} 

Popup { 
    id: temperatureParam 

    function openItem(model) 
    { 
     var p = model.param 

     params.itemAt(0).range.from = params.itemAt(1).range.from = p.min 
     params.itemAt(0).range.to = params.itemAt(1).range.to = p.max 

     params.itemAt(0).range.setValues(p.dayMin, p.dayMax) 
     params.itemAt(1).range.setValues(p.nightMin, p.nightMax) 

     open() 
    } 
} 

Antwort

3

Nach zum documentation:

Wenn Daten von C++ nach QML übertragen werden, bleibt der Besitz der Daten immer bei C++. Die Ausnahme von dieser Regel tritt auf, wenn ein QObject von einem expliziten C++ - Methodenaufruf zurückgegeben wird: In diesem Fall übernimmt die QML -Engine den Besitz des Objekts, es sei denn, der Eigentümer des Objekts wurde explizit so festgelegt, dass er durch Aufruf in C++ verbleibt QQmlEngine :: setObjectOwnership() mit QQmlEngine :: CppOwnership angegeben.

Im Allgemeinen muss eine Anwendung die Eigentumsrechte eines Objekts nicht explizit festlegen. Wie Sie here lesen können, hat ein Objekt, das von QML erstellt wird, standardmäßig JavaScriptOwnership.

Objekte, die von C++ - Methodenaufrufen zurückgegeben werden, werden ebenfalls auf JavaScriptOwnership gesetzt, aber dies gilt nur für explizite Aufrufe von Q_INVOKABLE Methoden oder Steckplätzen.

Da das Verfahren data ist keine explizite C++ Methodenaufruf, sollten Sie das Objekt Eigentum an QQmlEngine::JavaScriptOwnershipsetObjectOwnership()

im Allgemeinen also Aufruf gesetzt betrachten:

  • nicht QQmlEngine::CppOwnership, wenn Sie verwenden Sie möchte, dass QML das Objekt zerstört. Die zugehörigen Daten werden bei Bedarf gelöscht (d. H. Nachdem der Garbage Collector festgestellt hat, dass keine weiteren Referenzen auf den Wert vorhanden sind)
  • Eine QSharedPointer würde wahrscheinlich nicht funktionieren. Sie haben mehr Informationen here.
+0

Wow, ich wusste es nicht. Danke für die Antwort. Aber ich habe versucht, SetObjectOwnership und es funktioniert für mich viel schlimmer als deleteLater. Wenn ich deleteLater belasse, ist es sicher genug, wenn QQmlEngine und mein Modell im selben Thread erstellt werden. Nach dem Beenden der Funktion temperatureParam.openItem (QML) brauche ich dieses Objekt nicht mehr. Oder das Objekt kann vorher gelöscht werden? – lirik90

+0

@ lirik90 Danke an dich! Nun, ich habe nicht gesagt, die Codezeile 'deleteLater' zu entfernen. Entschuldigung, wenn ich mich nicht richtig erkläre :(Wenn 'data' während' temperatureParam.openItem' ausgeführt wird (bin ich richtig?), Dann denke ich, 'p' wird nicht gelöscht, es sei denn, Sie setzen seine Eigentümerschaft auf' QQmlEngine: : JavaScriptOwnership'. – Tarod