Wetter-Infos
Das Beispiel Wetterinfo zeigt, wie man die aktuelle Position des Benutzers verwendet, um lokale Inhalte von einem Webdienst in einem C++-Plugin für Qt Quickunter Verwendung von Qt Positioning.
Schlüssel Qt Positioning Klassen, die in diesem Beispiel verwendet werden:
Ausführen des Beispiels
Zum Ausführen des Beispiels von Qt Creatorzu starten, öffnen Sie den Modus Welcome und wählen Sie das Beispiel unter Examples aus. Weitere Informationen finden Sie unter Erstellen und Ausführen eines Beispiels.
Anbieter von Wetterdaten
Das Beispiel verwendet mehrere nicht miteinander verbundene Wetterdatenanbieter:
Der zu verwendende Anbieter wird zur Laufzeit automatisch ausgewählt und kann geändert werden, wenn der ausgewählte Anbieter nicht verfügbar ist. Er kann jedoch nicht manuell festgelegt werden.
Hinweis: Für alle Anbieter werden kostenlose Tarife verwendet, was gewisse Beschränkungen für die Anzahl der Wetteranfragen mit sich bringt. Wenn diese Grenzen überschritten werden, sind die Anbieter vorübergehend nicht verfügbar. Wenn alle Anbieter nicht mehr verfügbar sind, kann die Anwendung keine Wetterinformationen mehr anzeigen. In diesem Fall muss gewartet werden, bis mindestens einer der Anbieter wieder verfügbar ist.
Datenmodelle der Anwendung
Der wichtigste Teil dieses Beispiels ist das Datenmodell der Anwendung, das in den Klassen WeatherData
und AppModel
enthalten ist. WeatherData
repräsentiert die Wetterinformationen, die aus dem HTTP-Dienst stammen. Es handelt sich um eine einfache Datenklasse, aber wir verwenden Q_PROPERTY, um sie später in QML darzustellen. Sie verwendet auch das Makro QML_ANONYMOUS, wodurch sie in QML erkannt wird.
class WeatherData : public QObject { Q_OBJECT Q_PROPERTY(QString dayOfWeek READ dayOfWeek WRITE setDayOfWeek NOTIFY dataChanged) Q_PROPERTY(QString weatherIcon READ weatherIcon WRITE setWeatherIcon NOTIFY dataChanged) Q_PROPERTY(QString weatherDescription READ weatherDescription WRITE setWeatherDescription NOTIFY dataChanged) Q_PROPERTY(QString temperature READ temperature WRITE setTemperature NOTIFY dataChanged) QML_ANONYMOUS public: explicit WeatherData(QObject *parent = 0); WeatherData(const WeatherData &other); WeatherData(const WeatherInfo &other); QString dayOfWeek() const; QString weatherIcon() const; QString weatherDescription() const; QString temperature() const; void setDayOfWeek(const QString &value); void setWeatherIcon(const QString &value); void setWeatherDescription(const QString &value); void setTemperature(const QString &value); signals: void dataChanged(); };
AppModel
modelliert den Zustand der gesamten Anwendung. Beim Start erhalten wir die Standardposition der Plattform mit QGeoPositionInfoSource::createDefaultSource().
AppModel::AppModel(QObject *parent) : QObject(parent),d(new AppModelPrivate) { d->src = QGeoPositionInfoSource::createDefaultSource(this); if (d->src) { d->useGps = true; connect(d->src, &QGeoPositionInfoSource::positionUpdated, this, &AppModel::positionUpdated); connect(d->src, &QGeoPositionInfoSource::errorOccurred, this, &AppModel::positionError);#if QT_CONFIG(permissions) QLocationPermission permission; permission.setAccuracy(QLocationPermission::Precise); permission.setAvailability(QLocationPermission::WhenInUse); switch (qApp->checkPermission(permission)) { case Qt::PermissionStatus::Undetermined: qApp->requestPermission(permission, [this](const QPermission& permission) { if (permission.status() == Qt::PermissionStatus::Granted) d->src->startUpdates(); sonstpositionError(QGeoPositionInfoSource::AccessError); }); break; case Qt::PermissionStatus::Denied: qWarning("Location permission is denied"); positionFehler(QGeoPositionInfoSource::AccessError); break; case Qt::PermissionStatus::Granted: d->src->startUpdates(); break; }#else d->src->startUpdates();#endif} else { d->useGps = false; d->city = "Brisbane"; emit cityChanged(); requestWeatherByCity(); } QTimer *refreshTimer = new QTimer(this); connect(refreshTimer, &QTimer::timeout, this, &AppModel::refreshWeather); using namespace std::chrono; refreshTimer->start(60s); }
Wenn keine Standardquelle verfügbar ist, nehmen wir eine statische Position und holen uns das Wetter für diese. Wenn wir jedoch eine Positionsquelle haben, verbinden wir deren positionUpdated()-Signal mit einem Slot auf AppModel
und rufen startUpdates() auf, wodurch die regelmäßige Aktualisierung der Geräteposition beginnt.
Wenn eine Positionsaktualisierung empfangen wird, verwenden wir den Längen- und Breitengrad der zurückgegebenen Koordinate, um die Wetterdaten für den angegebenen Standort abzurufen.
void AppModel::positionUpdated(QGeoPositionInfo gpsPos) { d->coord = gpsPos.coordinate(); if (!d->useGps) return; requestWeatherByCoordinates(); }
Um die Benutzeroberfläche über diesen Prozess zu informieren, wird das Signal cityChanged()
ausgegeben, wenn eine neue Stadt verwendet wird, und das Signal weatherChanged()
, wenn eine Wetteraktualisierung erfolgt.
Das Modell verwendet auch das Makro QML_ELEMENT, das es in QML verfügbar macht.
class AppModel : public QObject { Q_OBJECT Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) Q_PROPERTY(bool hasSource READ hasSource NOTIFY readyChanged) Q_PROPERTY(bool hasValidCity READ hasValidCity NOTIFY cityChanged) Q_PROPERTY(bool hasValidWeather READ hasValidWeather NOTIFY weatherChanged) Q_PROPERTY(bool useGps READ useGps WRITE setUseGps NOTIFY useGpsChanged) Q_PROPERTY(QString city READ city WRITE setCity NOTIFY cityChanged) Q_PROPERTY(WeatherData *weather READ weather NOTIFY weatherChanged) Q_PROPERTY(QQmlListProperty<WeatherData> forecast READ forecast NOTIFY weatherChanged) QML_ELEMENT public: explicit AppModel(QObject *parent = 0); ~AppModel(); bool ready() const; bool hasSource() const; bool useGps() const; bool hasValidCity() const; bool hasValidWeather() const; void setUseGps(bool value); QString city() const; void setCity(const QString &value); WeatherData *weather() const; QQmlListProperty<WeatherData> forecast() const; public slots: Q_INVOKABLE void refreshWeather(); signals: void readyChanged(); void useGpsChanged(); void cityChanged(); void weatherChanged(); };
Wir verwenden QQmlListProperty für die Wettervorhersageinformationen, die die Wettervorhersage für die nächsten Tage enthalten (die Anzahl der Tage ist anbieterspezifisch). Dies erleichtert den Zugriff auf die Vorhersage über QML.
Benutzerdefinierte Modelle für QML freigeben
Um die Modelle der QML-Oberflächenschicht zugänglich zu machen, verwenden wir die Makros QML_ELEMENT und QML_ANONYMOUS. Weitere Einzelheiten zu diesen Makros finden Sie in der Klassenbeschreibung QQmlEngine.
Um die Typen in QML verfügbar zu machen, müssen wir unseren Build entsprechend aktualisieren.
CMake-Build
Für einen CMake-basierten Build müssen wir das folgende zur CMakeLists.txt
hinzufügen:
qt_add_qml_module(weatherinfo URI Weather VERSION 1.0 SOURCES appmodel.cpp appmodel.h openmeteobackend.cpp openmeteobackend.h openweathermapbackend.cpp openweathermapbackend.h providerbackend.cpp providerbackend.h weatherapibackend.cpp weatherapibackend.h QML_FILES BigForecastIcon.qml ForecastIcon.qml WeatherIcon.qml WeatherInfo.qml RESOURCES icons/weather-few-clouds.svg icons/weather-fog.svg icons/weather-haze.svg icons/weather-icy.svg icons/weather-overcast.svg icons/weather-showers.svg icons/weather-sleet.svg icons/weather-snow.svg icons/weather-storm.svg icons/weather-sunny-very-few-clouds.svg icons/weather-sunny.svg icons/weather-thundershower.svg icons/weather-showers-scattered.svg icons/waypoint.svg )
qmake Build
Für einen qmake-Build müssen wir die Datei weatherinfo.pro
wie folgt ändern:
CONFIG += qmltypes QML_IMPORT_NAME = Weather QML_IMPORT_MAJOR_VERSION = 1 qml_resources.files = \ qmldir \ BigForecastIcon.qml \ ForecastIcon.qml \ WeatherIcon.qml \ WeatherInfo.qml \ icons/weather-few-clouds.svg \ icons/weather-fog.svg \ icons/weather-haze.svg \ icons/weather-icy.svg \ icons/weather-overcast.svg \ icons/weather-showers.svg \ icons/weather-showers-scattered.svg \ icons/weather-sleet.svg \ icons/weather-snow.svg \ icons/weather-storm.svg \ icons/weather-sunny-very-few-clouds.svg \ icons/weather-sunny.svg \ icons/weather-thundershower.svg \ icons/waypoint.svg qml_resources.prefix = /qt/qml/Weather RESOURCES += qml_resources
Instanziierung der Modelle in QML
Schließlich instanziieren wir in der eigentlichen QML die AppModel
:
Window { id: window AppModel { id: appModel onReadyChanged: { if (appModel.ready) statesItem.state = "ready" else statesItem.state = "loading" } } }
Sobald das Modell auf diese Weise instanziiert ist, können wir seine Eigenschaften an anderer Stelle im QML-Dokument verwenden:
BigForecastIcon { id: current Layout.fillWidth: true Layout.fillHeight: true weatherIcon: (appModel.hasValidWeather ? appModel.weather.weatherIcon : "sunny") }
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.