Unsolved How to fill data Qt Item Model
-
Hi,
I just want to use Qt/Qml in Android.
I fallow this video in case of learn Qt and QML talking.I want to get items from web page. I create one php file and returning String List. I called this php file in constructor block of OtItemModel which I just created. But When I run the code
sakinlerListesi.h
#ifndef SAKINLERLISTESI_H #define SAKINLERLISTESI_H #include <QAbstractListModel> #include <QDebug> //İnternet için #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QEventLoop> class SakinlerListesi : public QAbstractListModel { Q_OBJECT public: explicit SakinlerListesi(QObject *parent = nullptr); enum { aciklama }; // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual QHash<int, QByteArray> roleNames() const override; bool checkInternet(); void sakinAl(); private slots: void sakinAlCevap(QNetworkReply *reply); private: int sayac = 0; QList<QString> donenSakinler; }; #endif // SAKINLERLISTESI_H
sakinlerListesi.cpp
#include "sakinlerlistesi.h" SakinlerListesi::SakinlerListesi(QObject *parent) : QAbstractListModel(parent) { //Below function call the php request sakinAl(); //But unfotunately data donenSakinler.count() is zero in here! I don't know why? //do{}while(sayac<1); qDebug()<<donenSakinler; qDebug()<<donenSakinler.count(); } void SakinlerListesi::sakinAl() { if(!checkInternet()) { qDebug()<<"İnternet Yok!"; return; } QNetworkAccessManager * manager = new QNetworkAccessManager(this); QUrl url("https://www.mucipilbuga.com/XXX/aaa.php"); QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(sakinAlCevap(QNetworkReply *))); manager->get(request); } void SakinlerListesi::sakinAlCevap(QNetworkReply *reply) { QString gelenCevap = reply->readAll().trimmed(); //QMessageBox::information(this, "Dış IP Adresi", "Dış IP Adresiniz:\n" + gelenCevap); QString takas = gelenCevap; QStringList list1 = takas.split("#"); foreach(QString sakin, list1){ donenSakinler.append(sakin); } //qDebug()<<donenSakinler; sayac = 1; //delete reply->manager(); //Kaynağı siler... //reply->manager() = nullptr; //Kaynağı siler... } int SakinlerListesi::rowCount(const QModelIndex &parent) const { // For list models only the root node (an invalid parent) should return the list's size. For all // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. if (parent.isValid()) return 0; // FIXME: Implement me! qDebug()<<donenSakinler.size(); return donenSakinler.size(); } QVariant SakinlerListesi::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); // FIXME: Implement me! return QVariant(QStringLiteral("Deneme %1").arg(index.row())); } QHash<int, QByteArray> SakinlerListesi::roleNames() const { QHash<int, QByteArray> names; names[0] = "aciklama"; return names; } bool SakinlerListesi::checkInternet() { QNetworkAccessManager nam; QNetworkRequest req(QUrl("http://www.google.com")); QNetworkReply* replyCheckInternet = nam.get(req); QEventLoop loop; QObject::connect(replyCheckInternet, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); if (replyCheckInternet->bytesAvailable()) { delete replyCheckInternet; return true; } else { delete replyCheckInternet; return false; } }
How va I fill the data in Item Model with the names returning from my web page?
Regards,
Mucip:) -
@Mucip
YoursakinAlCevap()
is supposed to be fillingdonenSakinler
. We can't tell what data it receives to know what it is putting there, you need to put inqDebug()
statements.You look like you're calling
sakinAl()
very early.sakinAlCevap()
will not be called until the reply is received, yet you expectdonenSakinler
to be populated immediately after callingsakinAl()
, which will not be the case yet.Separately, your
SakinlerListesi::data()
should not return yourQVariant(QStringLiteral("Deneme %1").arg(index.row()))
unconditionally as you show, you must look at therole
parameter (i.e. only do so forQt::DisplayRole/EditRole
.Separately, your
QNetworkAccessManager * manager = new QNetworkAccessManager(this);
is leaked. -
Hi @JonB ,
Qdebug output is:() 0 () 0 0 0 qrc:/Page4Form.ui.qml:21:5: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function. ("1-Lütfü ULUMAN", "2-Duygu TESGİ", "3-Tevhide Hanım", "4-Kübra ÇELİK", "5-Kadir YALTIR", "6-Ahmet KOCAHAN", "7-Murat DENİZ", "8-Birdal ÖZCAN", "9-Ömer ORAK", "10-Berkin ALTUNSOY", "11-Volkan TONCA", "12-Ömer AKSOY", "13-Mucibirahman İLBUĞA", "14-Kerem KEPENCİ", "15-Hasan Masat", "16-Modüler Sigorta", "17-Eczane Uğurlu", "18-Gökhan KUŞÇU") ("1-Lütfü ULUMAN", "2-Duygu TESGİ", "3-Tevhide Hanım", "4-Kübra ÇELİK", "5-Kadir YALTIR", "6-Ahmet KOCAHAN", "7-Murat DENİZ", "8-Birdal ÖZCAN", "9-Ömer ORAK", "10-Berkin ALTUNSOY", "11-Volkan TONCA", "12-Ömer AKSOY", "13-Mucibirahman İLBUĞA", "14-Kerem KEPENCİ", "15-Hasan Masat", "16-Modüler Sigorta", "17-Eczane Uğurlu", "18-Gökhan KUŞÇU") 17:04:52: D:\Belgeler\Qt\build-MobilApt-Desktop_Qt_5_14_2_MSVC2017_64bit-Release\release\MobilApt.exe exited with code 0
As you see in the begining the " donenSakinler.count(); " retuen 0. I could not undrstand this?
But in the end I cann see the number and names filled in the donenSakinler statement.?!I could not understand when the system call data function. I need to fill donenSakinler statement first then call "data" function. But I don't know how to do this.
By the way "QVariant(QStringLiteral("Deneme %1").arg(index.row()))" is only test. I want to fill like
QVariant(QStringLiteral(donenSakinler[1]); QVariant(QStringLiteral(donenSakinler[2]); QVariant(QStringLiteral(donenSakinler[3]); QVariant(QStringLiteral(donenSakinler[4]); . . . . etc.
I could fill the donenSakinler QList but I can not load this list in to QtItemModel unfortunately yet. :(
Regards,
Mucip:) -
@JonB ,
By the way, I could not understand?
When th object callint rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
these two functions. How can I call them again after than internet request finished?
Regards,
Mucip:) -
@Mucip said in How to fill data Qt Item Model:
I need to fill donenSakinler statement first then call "data" function. But I don't know how to do this.
This way is not the best. You don't have to "force"
rowCount()
to be right from the start. Leave your request to fill the array in the background.You really need to read and understand what you're supposed to do when subclassing
QAbstractListModel
, https://doc.qt.io/qt-5/qabstractlistmodel.html#subclassing. When you put new data into the model (e.g. yourdonenSakinler.append(sakin)
, called when parsing the reply) you should be callingbegin
/endInsertRows()
as it explains there. Then any view attached to the model will see the additions.The above is the right way to go about things, but requires some understanding. Otherwise, you must find a way to block during
SakinlerListesi::SakinlerListesi()
till the reply is received synchronously, so that yourdata
/rowCount()
is valid before you try to read them. Which is not so nice. -
@Mucip said in How to fill data Qt Item Model:
How can I call them again after than internet request finished?
Read my post above which has just crossed with yours.
Basically you do not "call them again after than internet request finished?". You simply cannot afford to call them (to get the expected answer) until the request is finished. It's your task not to do so beforehand, else they will not be right. They just reflect whatever is in the data at the instant you do call them.
If you do the
beginInsertRows()
I mentioned then the Qt infrastructure will see your new rows and change their return values correspondingly.If you really want to be lazy and "block" until the request finishes, you can always put in a suitable
QEventLoop::exec()
, which you terminate from the requestfinished()
signal, just like you do for yourreplyCheckInternet
presently.