サンプルマップを使用したC ++のデータモデルとQMLの表現の関連付け





この投稿は、 「Smart Posts for Smart Posts」コンテストに参加しています。



次の問題を解決してみましょう。アプリケーションでピン付きカードを表示します。つまり、LBSアプリケーションに必要な標準機能を作成します。 さらに、MVCパラダイムでこれを行うには、つまり、C ++のデータモデルとコントローラー、およびQMLはUIに関連付けられたマッピングとロジックのみを処理します。 マップには標準のMap要素を使用し、同時にC ++およびQMLからのデータモデルのバインディングを扱います。





動作するには、インストール済みのQt SDK 1.1.4が必要です。 新しいプロジェクトを作成します:Qt Quick Application-> Qt Quick Components for Meego / Harmattan、そしてデフォルトですべて。 Qt Mobilitiyを使用するため、proファイルに追加する必要があります。



CONFIG += mobility
      
      







その後、C ++バインディングと2つのqmlファイル(main.qmlおよびMainPage.qml)を含む空のプロジェクトが作成されます。 メインには触れません。プラットフォームの標準である上部のステータスバーと下部のメニューが含まれています。 MainPageに必要なものをインポートする必要があります。



 import QtMobility.location 1.2
      
      







Page要素内のすべてを削除し、Mapに置き換えます。



 Map { id: map anchors.fill:parent plugin: Plugin {name:"nokia"} zoomLevel: 13 center: Coordinate { latitude: 55.755786; longitude: 37.617633 } }
      
      







プラグインの定義に注意を払います。これは、マップ内でNokia(Ovi)Mapsからタイルを取得するために記述する方法です。 他のプラグインを接続することは可能ですが、すぐに使用できるわけではありません。 次に、近似のレベルとマップの中心の座標を決定します。 私たちは始め、モスクワを見ます。



すべて順調ですが、少なくとも指のスクロールが必要です。 ネイティブコントロールはこれを行う方法を知らないので、自分で行います。 マップの上に、単一のタチをキャッチしてマップを移動するMouseAreaを追加します。



  MouseArea { anchors.fill:parent property int lastX : -1 property int lastY : -1 onPressed : { lastX = mouse.x; lastY = mouse.y; } onReleased : { lastX = -1; lastY = -1; } onPositionChanged: { if (lastX>=0) { map.pan(lastX- mouse.x, lastY - mouse.y) lastX = mouse.x lastY = mouse.y } } }
      
      







2本指ズームは、PinchArea要素を使用して同様の方法で処理できます。



次に、ピンを描画する必要があります。 マップコントロールは、それ自体でグラフィカルプリミティブとビットマップの両方のさまざまな要素のレンダリングをサポートしますが、これは動的にaddMapObjectメソッドとremoveMapObjectメソッドを介して実行できます。 もう1つのオプションはMapObjectViewを使用することですが、ドキュメントには「モデルデータについては、現在LandmarkModelのみがサポートされています。 他のタイプのモデルを使用すると、未定義の動作が発生します。」そしてLandmarkModelは、多くの制限と不必要なアクションを伴う暗い森です。 もっとシンプルなものが必要です。 したがって、独自の方法で進めますが、最初にC ++でモデルを処理します。



モデルは単純です。内部にはピンのリストがあり、各lat、lng、およびピンの画像のURLのimageSourceがあります。 しかし、ビューでは、latとlngではなく、画面上のXとYピンの絶対値を表示します。 また、リストにピンを追加するAddPinメソッドと、変更がありX値とY値を再計算したときにビューから呼び出されるDrawPinsを実装します。DrawPinsは、ビューから信号を受信できるようにパブリックスロットとして宣言する必要があります。



 class PinList : public QAbstractListModel //… void PinList::addPin(QString imageSource, double lat, double lng) { //      Pin *pin = new Pin(this); pin->imageSource = imageSource; pin->Lat = lat; pin->Lng = lng; beginInsertRows(QModelIndex(), this->Pins->length(), this->Pins->length()); this->Pins->append(pin); endInsertRows(); // view,    emit dataChanged(createIndex(0,0),createIndex(this->Pins->size(),0)); } //view       lat, lng   x,y (        0,0) void PinList::DrawPins(QString x,QString y,QString x_end,QString y_end, QString map_x, QString map_y) { //   map_first_lat = x.toDouble(); map_first_lng = y.toDouble(); map_second_lat = x_end.toDouble(); map_second_lng = y_end.toDouble(); map_x_end = map_x.toDouble(); map_y_end = map_y.toDouble(); // view,    emit dataChanged(createIndex(0,0),createIndex(this->Pins->size(),0)); } //  view     //     lat,lng  x,y QVariant PinList::data(const QModelIndex & index, int role) const { if (index.row() < 0 || index.row() > this->Pins->count()) return QVariant(); const Pin* pin = this->Pins->at(index.row()); QVariant result; switch (role) { case ImageSource: result = QVariant(pin->imageSource); break; case X: if ( pin->Lng > map_first_lng && pin->Lng < map_second_lng) { result =QVariant((map_x_end)*(pin->Lng - map_first_lng)/(map_second_lng - map_first_lng)); } break; case Y: if ( pin->Lat > map_second_lat && pin->Lat < map_first_lat) { result = QVariant(map_y_end*(pin->Lat - map_first_lat)/(map_second_lat - map_first_lat)); } break; } return result; }
      
      







次に、すべてを表示する必要があります。 これを行うには、ピンの外観を定義します。



  // Component { id: landmarkMapDelegate Item { id:land width: 20; height: 20 ; x: X y: Y Image { source:ImageSource } } }
      
      







地図の上にリピーターを描きます



  Item { anchors.fill:parent Repeater { model: pinlist delegate: landmarkMapDelegate } }
      
      







これは重要です。モデルはピンリスト識別子に関連付けられています。 この識別子は、C ++でモデルをバインドするために指定する必要があります。



DrawPins関数を宣言します。これは、マップの緯度と経度のコーナーを読み取り、モデルに渡します。



  function drawPins() { var topLeft = map.toCoordinate(Qt.point(0,0)) var bottomRight = map.toCoordinate(Qt.point(map.width, map.height)) pinlist.DrawPins(topLeft.latitude,topLeft.longitude,bottomRight.latitude,bottomRight.longitude, map.width,map.height); }
      
      







OnPositionChangesマップで呼び出します。



実際、モデルとビューを接続することはそのままです。



  //  PinList* pinList = new PinList(0); //   pinList->addPin("qrc:/icons/pin.png", 55.745, 37.6175); pinList->addPin("qrc:/icons/pin.png", 55.7575, 37.619697); pinList->addPin("qrc:/icons/pin.png", 55.751667, 37.617778); //    viewer->rootContext()->setContextProperty("pinlist", pinList); // qml viewer->setMainQmlFile(QLatin1String("qml/untitled/main.qml"));
      
      





それだけです



ソースコード






All Articles