2017-02-07 7 views
2

ich habe folgende Scrollview mit Listview innen bekam:QML Listenansicht Artikel verschwinden beim Scrollen

ScrollView{ 
    anchors.fill: parent 
    ListView{ 
     id: lvCommitsBranch 
     model: git.getCommitsBranch(); 
     clip: true 
     delegate: Rectangle { 
      height: 100 
      width: parent.width 
      Text { 
       anchors.left: parent.left 
       font.bold: true 
       text:model.author 
       id:txtName 
      } 
      Text{ 
       anchors.left: parent.left 
       anchors.top:txtName.bottom 
       font.pixelSize: 10 
       text:model.email 
       id: txtEmail 
      } 
      Text { 
       anchors.left: parent.left 
       anchors.top:txtEmail.bottom 
       text: model.message + ' ' + model.hash 
       id: txtMsg 
      } 
      MouseArea{ 
       anchors.fill: parent 
       onClicked: { 
        lvCommitsBranch.currentIndex = index; 
        console.log('Msg: ' + model.message); 
        console.log('Hash: ' + model.hash); 
       } 
       acceptedButtons: Qt.LeftButton | Qt.RightButton 
      } 
     } 
    } 
} 

Das Problem ist, dass, wenn ich einige Elemente bewegen verschwinden (jeweils zufällig Zeit und manchmal muss ich schnell bewegen, aber nicht immer).

enter image description here

Wenn ich auf den Artikel klicken, die nicht verschwunden sind, bekomme ich undefined auf alle die Eigenschaften des Modells. Wenn Mousearea des onclick ausgelöst wird er druckt die folgende:

qml: Nachricht: undefined

qml: Hash: undefined

ich das Modell Infos von einem Verfahren erhalten (QAbstractListModel), der zurückgegeben wird von meiner git benutzerdefinierten Komponente.

Das ist mein QAbstractListModel:

Header:

class CommitsBranch : public QAbstractListModel 
{ 
    Q_OBJECT 
public: 
    enum Roles { 
     AuthorRole, 
     EMailRole, 
     MsgRole, 
     DateRole, 
     HashRole 
    }; 
    explicit CommitsBranch(QObject *parent = 0); 
    CommitsBranch(Repository *repo); 
public: 
    virtual int rowCount(const QModelIndex &parent) const override; 
    virtual QVariant data(const QModelIndex &index, int role) const override; 
protected: 
    // return the roles mapping to be used by QML 
    virtual QHash<int, QByteArray> roleNames() const override; 
private: 
    QList<Commit> m_data; 
    QHash<int, QByteArray> m_roleNames; 

}; 

cav:

CommitsBranch::CommitsBranch(QObject *parent) 
    : QAbstractListModel(parent) 
{ 
} 

CommitsBranch::CommitsBranch(Repository *repo) 
{ 
    m_roleNames[AuthorRole] = "author"; 
    m_roleNames[EMailRole] = "email"; 
    m_roleNames[MsgRole] = "message"; 
    m_roleNames[DateRole] = "date"; 
    m_roleNames[HashRole] = "hash"; 

    /* 
    here we append the m_data (QList) Items using libgit2 methods 
    */ 

} 

int CommitsBranch::rowCount(const QModelIndex &parent) const 
{ 
    Q_UNUSED(parent); 
    return m_data.count(); 
} 

QVariant CommitsBranch::data(const QModelIndex &index, int role) const 
{  
    // this function returns the required data 
} 

QHash<int, QByteArray> CommitsBranch::roleNames() const 
{ 
    return m_roleNames; 
} 

Und git ist nur eine Klasse, die von QObject erbt und es hat die folgende Methode:

Q_INVOKABLE QObject* getCommitsBranch(); 
QObject *Git::getCommitsBranch() 
{ 
    CommitsBranch* files = new CommitsBranch(repo.data()); 
    return files; 
} 

Ich bekomme das gleiche Verhalten ohne Scrollview. Wenn mehr Informationen benötigt werden, werde ich diese Frage bearbeiten, danke!

EDIT: Wenn ich ein Repository mit einer Menge von commits (mehr Zeilen auf die Listview) nehmen, wird auch die Erhöhung der CacheBuffer nicht helfen, wenn ich ein wenig blättern alle Elemente verschwinden.

+0

Das Problem wahrscheinlich von der automatischen Erstellung und Zerstörung von Delegierten, die von der Ansicht stammt, wie Sie blättern. Eine dreckige schnelle Lösung wäre es, den 'cacheBuffer' der Ansicht zu erhöhen - das ist die Anzahl der Pixel, die geladen werden sollen. Es ist bekannt, dass QML manchmal [verliert die Spur von seinen Schafen] (http://stackoverflow.com/questions/33792876/qml-garbage-collection-deletes-objects-still-in-use) sozusagen, überprüfen, ob Scrollen nicht Löschen Sie nicht versehentlich die tatsächlichen Modellelemente. – dtech

+0

Ich habe versucht, den 'cacheBuffer' auf 100 zu erhöhen und das Problem besteht immer noch. Ich habe es wieder auf 1000 geändert und jetzt verschwinden die Elemente nicht, aber manchmal werde ich immer noch undefiniert in den Eigenschaften des Objekts (auch einige seltsame visuelle Bugs wie Text verschoben) –

+0

Versuchen Sie ein 'Item' um das 'Rectangle' in Ihrem Delegaten zu wickeln . Wie 'delegate: Item {Rectangle {...}}' – DuKes0mE

Antwort

3

Das Problem hier ist, dass standardmäßig, wenn Sie ein QObject * zurückgeben, wird das Eigentum an QML übertragen.

http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership

Die Ausnahme von dieser Regel ist, wenn ein QObject von einem expliziten C++ Methodenaufruf zurückgegeben wird: in diesem Fall nimmt der QML Motor Besitz des Objekts, es sei denn, das Eigentum an dem Objekt hat explizit festgelegt, um mit C++ zu bleiben, indem QQmlEngine :: setObjectOwnership() mit QQmlEngine :: CppOwnership aufgerufen wird.

Sie haben das zurück QObject * Eigentum manuell einstellen, damit es nicht von dem QML Motor zerstört werden:

QObject *Git::getCommitsBranch() 
{ 
    CommitsBranch* files = new CommitsBranch(repo.data()); 

    QQmlEngine::setObjectOwnership(files, QQmlEngine::CppOwnership) 

    return files; 
} 

Beachten Sie, dass ein Speicherleck als CommitsBranch Objekt haben wird nie gelöscht werden. Aber zumindest sollten deine QML-Gegenstände nicht mehr verschwinden!

EDIT: Wie vorgeschlagen, dass Sie etwas tun können den Speicherverlust zu vermeiden:

// CommitsBranch Constructor 
CommitsBranch::CommitsBranch(Repository *repo, QObject *parent) : 
    QAbstractListModel(parent) { /*stuff*/ } 

QObject *Git::getCommitsBranch() 
{ 
    // Setting ownership is not necessary if you pass the parent to the QAbstractListModel 
    CommitsBranch* commits = new CommitsBranch(repo.data(), this); 

    return files; 
} 
+0

Sie irren sich nicht, aber die CommitsBranch scheint das Listenmodell zu sein, das nicht von QML gelöscht werden kann, während ich die Liste scrolle !? – Xander

+0

Das Modell wird nicht von QML beim Scrollen der Liste zerstört, aber wenn QML davon ausgeht, dass das Modell nicht mehr benötigt wird. Es kann jederzeit passieren. Wenn sich die Liste nicht bewegt, muss QML nicht auf das Modell zugreifen, sodass Sie nicht erkennen können, ob das Modell vorhanden ist oder nicht. Ein Scroll wird jedoch QML zwingen, das Modell zu lesen, und Sie werden feststellen, dass etwas ausgeschaltet ist. – Blabdouze

+0

Ich werde es so schnell wie möglich testen. Um das Speicherleck zu vermeiden, sollte ich einen QSharedPointer verwenden oder es wäre keine gute Idee? –

Verwandte Themen