QML Map with many items takes a long time to shut down
Unsolved
QML and Qt Quick
-
I am currently working on a small test application which uses QML Map to display a collection of paths. Each path is a list of coordinates. For each path, I create a MapPolyline with the coordinates as its path property, and then for each coordinate on the path, I create a MapQuickItem with that coordinate as its coordinate property. I am currently rendering 500 paths each containing 100 coordinates. The application starts up reasonably quickly but does not ever seem to finish shutting down on close. I am wondering if my approach is somehow unreasonably inefficient.
mymap.qml:
import QtQuick 2.0 import QtPositioning 5.6 import QtLocation 5.6 import com.plexsys.fpscounter 1.0 Map { id: myMap zoomLevel: 4 center { latitude: 0; longitude: 0 } Plugin { id: myPlugin name: "itemsoverlay" } plugin: myPlugin MapPolyline { id: primeMeridian line.width: 3 line.color: "green" path: [ { latitude: -90, longitude: 0 }, { latitude: 0, longitude: 0 }, { latitude: 90, longitude: 0} ] } MapPolyline { id: equator line.width: 3 line.color: "green" path: [ { latitude: 0, longitude: -180 }, { latitude: 0, longitude: -90 }, { latitude: 0, longitude: 0 }, { latitude: 0, longitude: 90 }, { latitude: 0, longitude: 180 }, ] } FpsCounter { id: fps_text x: 0 y: 0 z: parent.z + 1 width: 50 height: 25 Text { anchors.centerIn: parent text: fps_text.fps.toFixed(2) } } Repeater { model: randomPathModel MapPolyline { line.width: 2 line.color: "blue" path: randomPath.points Component.onCompleted: { myMap.addMapItem(this) } } } Repeater { model: randomPathModel Repeater { model: randomPath MapQuickItem { coordinate: randomPoint sourceItem: Rectangle { width: 16 height: 16 color: "red" } anchorPoint.x: sourceItem.width / 2 anchorPoint.y: sourceItem.height / 2 Component.onCompleted: { myMap.addMapItem(this) } } } } }
QMLMapTester.cpp:
#include <QtCore/QUrl> #include <QtWidgets/QApplication> #include <QtWidgets/QMainWindow> #include <QtWidgets/QHBoxLayout> #include <QtQuick/QQuickView> #include <QtQml/QQmlContext> #include "RandomPathModel.h" #include "FpsCounter.h" //////////////////////////////////////////////////////////////////////////////// class MyMainWindow : public QMainWindow { public: MyMainWindow(QWidget* parent = nullptr) : QMainWindow(parent) { QWidget* mainWidget = new QWidget(this); setCentralWidget(mainWidget); QHBoxLayout* layout = new QHBoxLayout(mainWidget); m_view = new QQuickView; m_view->setResizeMode(QQuickView::SizeRootObjectToView); QWidget* container = QWidget::createWindowContainer(m_view, this); layout->addWidget(container); } QQuickView* getView() { return m_view; } private: QQuickView* m_view; }; //////////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { qmlRegisterType<FpsCounter>("com.plexsys.fpscounter", 1, 0, "FpsCounter"); QApplication app(argc, argv); MyMainWindow mainWindow; RandomPathModel rpm; rpm.addPaths(500, 100); QQuickView* view = mainWindow.getView(); QQmlContext* context = view->rootContext(); context->setContextProperty("randomPathModel", &rpm); view->setSource(QUrl("mymap.qml")); mainWindow.show(); return app.exec(); }
RandomPathModel.h:
#ifndef _QMLMAPTESTER_RANDOMPATHMODEL_H #define _QMLMAPTESTER_RANDOMPATHMODEL_H //////////////////////////////////////////////////////////////////////////////// #include "RandomPointModel.h" #include <QtCore/QSharedPointer> //////////////////////////////////////////////////////////////////////////////// class RandomPathModel : public QAbstractListModel { Q_OBJECT public: RandomPathModel(QObject* parent = nullptr); ~RandomPathModel(); Q_PROPERTY(int length READ length CONSTANT) enum Roles { PathRole = Qt::UserRole + 1 }; int rowCount(const QModelIndex& parent) const override; int length() const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; void addPaths(int iNumPaths, int iNumPoints); protected: QHash<int, QByteArray> roleNames() const override; private: typedef QSharedPointer<RandomPointModel> RandomPointModelSharedPointer; typedef QList<RandomPointModelSharedPointer> PathList; PathList m_paths; }; //////////////////////////////////////////////////////////////////////////////// #endif // _QMLMAPTESTER_RANDOMPATHMODEL_H
RandomPointModel.h:
#ifndef _QMLMAPTESTER_RANDOMPOINTMODEL_H #define _QMLMAPTESTER_RANDOMPOINTMODEL_H //////////////////////////////////////////////////////////////////////////////// #include <QtCore/QAbstractListModel> #include <QtCore/QList> #include <QtCore/QVariantList> #include <QtPositioning/QGeoCoordinate> //////////////////////////////////////////////////////////////////////////////// class RandomPointModel : public QAbstractListModel { Q_OBJECT public: RandomPointModel(QObject* parent = nullptr); ~RandomPointModel(); enum Roles { PointRole = Qt::UserRole + 1 }; int rowCount(const QModelIndex& parent) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; void addPoints(int iNumPoints); Q_PROPERTY(QVariantList points READ points NOTIFY pointsChanged); const QVariantList& points() const; signals: void pointsChanged(const QVariantList&); protected: QHash<int, QByteArray> roleNames() const override; private: QVariantList m_points; }; //////////////////////////////////////////////////////////////////////////////// #endif // _QMLMAPTESTER_RANDOMPOINTMODEL_H
The model implementations are fairly obvious but I can include them if they matter.