2017-04-25 6 views
0

Meine QML ListView zeigt meine Daten nicht an, bis ich sie mit der Maus störe (zB ziehe sie einfach hoch und runter.) Danach zeigt die Ansicht das Modell ohne Problem, bis es leer ist, und dann muss ich noch einmal stören, damit es wieder funktioniert. Gibt es eine Möglichkeit, diese ListView in Arbeit zu treten?ListView zeigt zunächst keine Daten an

Ich benutze Qt 5.8 auf Linux 14.04. Mein Modell ist eine Unterklasse von QAbstractListModel. Ich baue es, indem ich dem AbstractItemModel Example folge. Der Hauptunterschied besteht darin, dass mein Listenmodell eine Eigenschaft einer Entität ist und nicht mit setContextProperty in main.cpp festgelegt ist.

Es gibt ein paar ähnliche Probleme hier auf SO über die ListView s nicht zu aktualisieren, aber keine scheint nur ein Problem am Anfang zu haben. Die meisten von ihnen auf den OP betreffen manuell dataChanged statt beforeInsertRows() & endInsertRows() Aufruf - beide Methoden Ich rufe (siehe unten.)

Mein ListView in einem Artikel ist mit einem SceneLoader geladen.

I posted all the relevant code here, weil ich ein wenig misstrauisch bin, wie ich die Layouts auf mein ListView (vielleicht, dass es verursacht? Vielleicht ist meine Hierarchie gebrochen ist? Ich habe, dass, obwohl zu beweisen, nicht in der Lage gewesen.)

obwohl

kurz gesagt,

Listview:

ListView { 
    anchors.fill: parent 
    model: sceneGraph.blobs 
    delegate: delegate 
} 

BlobModel.cpp:

auto BlobModel::addBlob(const BlobPointDataPtr& data) -> void 
{ 
    // ... 

    // Each blob has a uuid 

    const auto idx = Contains(uuid); 
    if (-1 != idx) 
    { 
     blobs_[idx]->Update(data); 
     Q_EMIT dataChanged(createIndex(idx, 0), createIndex(idx, 0)); 
    } 
    else 
    { 
     beginInsertRows(QModelIndex(), rowCount(), rowCount()); 
     blobs_ << new Blob{data, id_count_}; id_count_++; 
     endInsertRows(); // responsible for the QQmlChangeSet 

     Q_EMIT dataChanged(createIndex(rowCount(), 0), createIndex(rowCount(), 0)); 
    } 
} 

Auch auf meinem Terminal, erhalte ich die Meldung:

QObject::connect: Cannot queue arguments of type 'QQmlChangeSet' 
(Make sure 'QQmlChangeSet' is registered using qRegisterMetaType().) 

Dies scheint durch endInsertRows() emittiert werden, aber ich bin mir nicht sicher, warum . In der Vergangenheit bestand die Lösung darin, den fehlenden Typ z.B.qRegisterMetaType<QQmlChangeSet*>("QQmlChangeSet"); aber das scheint kein öffentlicher Typ mit Qt zu sein, und weil alles meistens ohne es funktioniert, bin ich mir nicht sicher, dass das genau das Problem ist.

+1

Ich habe Ihren Code mit Ihren Angaben so gut wie möglich getestet. Ich habe Ihr Blob-Objekt zur Vereinfachung durch QStrings ersetzt. Ich habe addBlob() genau wie das AbstractItemModel Beispiel gemacht. Es hat gut für mich funktioniert. [Code hier] (https://gist.github.com/anonymous/1a41d90c212c73086fe81c41374b9661) –

+0

Wie haben Sie das Modell bevölkert?Ich fand, dass es gut funktionierte, wenn Anfangsdaten im Modell existierten, das Problem war wirklich nur, wenn das Modell leer war (also beim Start oder wenn das Modell geleert wurde). Danke fürs anschauen, ich werde versuchen, tatsächlich zu erstellen ein minimales Beispiel, und dann versuche ich es mit Strings wie in Ihrem Beispiel, um zu sehen, ob das einen Unterschied macht. – Matt

+0

hmm, ich habe gerade ein [minimales kompilierbares Beispiel] (https://github.com/kheaactua/listview_issue/tree/master/listview_issue) eingerichtet, und es funktioniert auch. Am Morgen füge ich etwas mehr hinzu, um es näher an meinen ursprünglichen Code zu bringen, um zu sehen, wo das Problem beginnt (und dann diesen Kommentar lösche). – Matt

Antwort

0

Das Problem, wie in den Kommentaren darauf hingewiesen, war, dass ich mein Modell außerhalb des Hauptthreads änderte.

Mein Code wurde so eingerichtet, dass ein anderer Thread Zusätze zu meinem Modell durch direkten Aufruf addData auslösen würde. Der Grund, warum mein minimales Beispiel dies nicht replizieren konnte, war, dass ich darin einen QTimer verwendete, um den anderen Thread zu simulieren, aber QTimer läuft auch auf dem Hauptthread.

Die Lösung war, meinen direkten Anruf zu addData(data) zu ändern, um ein Signal zu senden, um die Hinzufügung zu tun und so die tatsächliche Arbeit zurück zum Hauptfaden zu bewegen.