, QML- C++ , QML C++ , GET/POST- JSON-.
-, // , .
«qt_api», «test.php». :
<? echo json_encode(json_decode( '{ "done" : { "boolean" : true, "number" : 123, "list" : [ "field1", "field2", "field3", "field4", "field5" ] } }' )); ?>
JSON, «test.php» (http://localhost/qt_api/test.php) .
C++ Qt Creator: «Sample» -> « …» -> «C++» / « C++». «Backend», «QQuickItem»
[. 4] , :

«», «». «backend.h». :
#ifndef BACKEND_H #define BACKEND_H #include <QQmlApplicationEngine> #include <QQuickItem> #include <QtQuick> #include <QNetworkAccessManager> class Backend : public QQuickItem { Q_OBJECT public: explicit Backend(QQuickItem *parent = 0); Q_INVOKABLE void makeRequest(int id); private: QQmlApplicationEngine engine; QObject * mainWindow; QObject * lvList; QObject * btnRequest; QNetworkAccessManager * namRequest; static const QString color_example; signals: private slots: void slotRequestFinished(QNetworkReply*); }; #endif
.
. ( explicit). , , . Qt . , ( , , ), , Qt .
makeRequest. QML-, Q_INVOKABLE. id ( ).
(private) . QQmlApplicationEngine QML-. QObject QML
[. 5] . QNetworkAccessManager (- DefaultHttpClient Android). , QML.
. , -. / — Qt, , , . :
void mySignal();
:
emit mySignal();
, ( connect()) . , , , - -. , namRequest. (slotRequestFinished(QNetworkReply*)) — - QNetworkAccessManager: , namRequest finished(QNetworkReply*), , (QNetworkReply).
«backend.cpp», :
#include "backend.h" const QString Backend::color_example = "#000000"; Backend::Backend(QQuickItem *parent) : QQuickItem(parent) { engine.rootContext()->setContextProperty("color_example", color_example); engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); mainWindow = engine.rootObjects().value(0); lvList = mainWindow->findChild<QObject*>("lvList"); btnRequest = mainWindow->findChild<QObject*>("btnRequest"); engine.rootContext()->setContextProperty("backend", this); namRequest = new QNetworkAccessManager(this); connect(namRequest, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotRequestFinished(QNetworkReply*))); } void Backend::makeRequest(int id) { btnRequest->setProperty("enabled", "false"); // btnRequest->property("enabled"); QString prepareRequest("http://localhost/qt_api/test"); // HttpGet prepareRequest.append("?id="); prepareRequest.append(QString::number(id)); qDebug(prepareRequest.toUtf8()); QNetworkRequest request(QUrl(prepareRequest.toUtf8())); namRequest->get(request); // HttpPost /*QNetworkRequest request(QUrl(prepareRequest.toUtf8())); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QString params("id="); params.append(QString::number(id)); qDebug(params.toUtf8()); namRequest->post(request, QByteArray(params.toUtf8()));*/ } void Backend::slotRequestFinished(QNetworkReply * reply) { if (reply->error() != QNetworkReply::NoError) { qDebug(reply->errorString().toUtf8()); } else { QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll()); QJsonObject jsonObj; QJsonValue jsonVal; QJsonArray jsonArr; jsonObj = jsonDoc.object(); jsonVal = jsonObj.value("done"); if (!jsonVal.isNull() && jsonVal.isObject()) { jsonObj = jsonVal.toObject(); jsonVal = jsonObj.value("number"); if (!jsonVal.isNull() && jsonVal.isDouble()) { qDebug(QString::number(jsonVal.toDouble(), 'f', 3).toUtf8()); } } if (jsonDoc.object().value("done").toObject().value("boolean").toBool()) { qDebug("json true"); } else { qDebug("json false"); } jsonArr = jsonDoc.object().value("done").toObject().value("list").toArray(); QMetaObject::invokeMethod(lvList, "clear"); for (int i=0; i<jsonArr.size(); i++) { QVariantMap map; map.insert("name", jsonArr.at(i).toString()); QMetaObject::invokeMethod(lvList, "append", Q_ARG(QVariant, QVariant::fromValue(map))); } } btnRequest->setProperty("enabled", "true"); reply->deleteLater(); }
, . : .
QML- QQmlApplicationEngine.
QML:
mainWindow = engine.rootObjects().value(0);
objectName, QML. lvList:
lvList = mainWindow->findChild<QObject*>("lvList")
«backend» Backend. ( Q_INVOKABLE-) QML:
engine.rootContext()->setContextProperty("backend", this);
«color_example» QML:
engine.rootContext()->setContextProperty("color_example", color_example);
namRequest:
namRequest = new QNetworkAccessManager(this);
finished(QNetworkReply*) slotRequestFinished(QNetworkReply*):
connect(namRequest, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotRequestFinished(QNetworkReply*)))
connect 4 :
— , ;
— ;
— , ( );
— , .
makeRequest. , :
btnRequest->setProperty("enabled", "false")
QML ( ). QString:
QString prepareRequest(«http://localhost/qt_api/test");
GET- , :
prepareRequest.append("?id="); prepareRequest.append(QString::number(id));
int- ( makeRequest) QString. QString::number().
(QString QByteArray):
qDebug(prepareRequest.toUtf8())
QNetworkRequest QNetworkAccessManager GET-:
QNetworkRequest request(QUrl(prepareRequest.toUtf8()))
POST- , . , POST-, , CodeIgniter', «Disallowed Characters Error», .
, , .
, , , :
if (reply->error() != QNetworkReply::NoError) { qDebug(reply->errorString().toUtf8()); }
, . QJsonDocument JSON-. QJsonDocument QJsonDocument::fromJson(reply->readAll()), : reply->readAll(). , QNetworkReply, , ( - ).
JSON- QJsonDocument:
jsonObj = jsonDoc.object();
QJsonValue «done» JSON-:
jsonVal = jsonObj.value("done");
QJsonValue — JSON-, ( , , ..). QJsonValue . , QJsonValue JSON- QJsonValue ( «number») . , , QJsonValue double. «number» (3 ).
«boolean» «done» .
JSON- Qt: JSON- , ( Android, , JSONException). (, ), .
, Qt «» JSON-, , , JSON' .
QML JSON-, .
JSON- «list» QJsonArray:
jsonArr = jsonDoc.object().value("done").toObject().value("list").toArray();
«clear» «lvList» ( «clear» ListView QML- ):
QMetaObject::invokeMethod(lvList, "clear");
«lvList» JSON- — -, , «name» (, ListView?):
QVariantMap map; map.insert("name", jsonArr.at(i).toString());
«append» «lvList» ( ):
QMetaObject::invokeMethod(lvList, "append", Q_ARG(QVariant, QVariant::fromValue(map)));
QMetaObject::invokeMethod() :
— — , ;
— — , «lvList»;
— — , «append», «map».
:
btnRequest->setProperty("enabled", «true");
:
reply->deleteLater()
. «main.cpp»:
#include <QApplication> #include "backend.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); new Backend(); return app.exec(); }
«Backend», .
«clear», «append» ListView («lvList») «main.qml»:
function clear() { lvList.model.clear() } function append(newElement) { lvList.model.append(newElement) }
C++ «append» ( ), .
:
model: ListModel {
, makeRequest() Backend:
Button { objectName: "btnRequest" property int _id: 3 width: mainWindow.width / 4.5 height: mainWindow.height / 10 x: mainWindow.width - width y: mainWindow.height - height style: ButtonStyle { background: ButtonBackground { border.color: color_example } label: ButtonLabel { text: "Request" } } onClicked: backend.makeRequest(_id) }
«btnRequest», , C++ ,
property int _id: 3
— - QML-: «property», , . : id_._.
. -, :
background: ButtonBackground { border.color: color_example }
, «color_example» «Backend»? -, :
onClicked: backend.makeRequest(_id)
, , , ( property «_id», ).
«main.qml»:
import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.2 import "QMLs" ApplicationWindow { id: mainWindow objectName: "mainWindow" visible: true width: 640 height: 480 color: "#F0F0FF" Button { function hello() { if (textField.text != "") { text.text = ", <b>" + textField.text.toUpperCase() + "</b>!" } } width: mainWindow.width / 2.5 height: mainWindow.height / 10 x: 0 y: mainWindow.height - height style: ButtonStyle { background: ButtonBackground {} label: ButtonLabel { text: "" } } onClicked: hello() } TextField { id: textField width: parent.width height: parent.height / 10 horizontalAlignment: Text.AlignHCenter placeholderText: " " validator: RegExpValidator { regExp: /[--a-zA-Z]{16}/ } style: TextFieldStyle { background: Rectangle {color: "white"} textColor: "#00AAAA" placeholderTextColor: "#00EEEE" font: font.capitalization = Font.Capitalize, font.bold = true, font.pixelSize = mainWindow.height / 25 } Keys.onPressed: { if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return || event.key == Qt.Key_Back) { Qt.inputMethod.hide() loader.forceActiveFocus() event.accepted = true } } } Text { id: text y: textField.height width: parent.width height: parent.height / 10 font.pixelSize: height / 2 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter wrapMode: Text.WordWrap } ListView { id: lvList objectName: "lvList" y: text.y + text.height width: parent.width height: parent.height * 0.3 clip: true spacing: 8 model: ListModel {
, . «Request» ( iPhone ) :

:
localhost/qt_api/test?id=3
123.000
json trueそうです。 :). (https://www.dropbox.com/s/to9kk0l71d6ma4h/Sample.zip).
, Qt:
// QSettings, , QSettings settings("settings.ini", QSettings::IniFormat); // , QString stringToSave; // , QDate QDate date = QDate::currentDate(); // stringToSave = date.toString("ddd-dd-MM-yyyy"); // id QUuid QUuid uniq_id = QUuid::createUuid(); // id stringToSave.append(" id="); stringToSave.append(uniq_id.toByteArray()); // settings.setValue("value1", stringToSave); settings.sync(); // qDebug(settings.value("value1").toString().toUtf8());
, . , — Android . — , ApplicationWindow
[. 7] . — «Backend» QML :
engine.rootContext()->setContextProperty("screen_width", this->width()); engine.rootContext()->setContextProperty("screen_height", this->height());
QML- «ApplicationWindow» :
ApplicationWindow { . . . width: screen_width height: screen_height color: "#F0F0FF" . . .
:). , . Android ( , , Qt, , ), . «» -> «Android» -> «».