GeoJson ビューア(QML)
GeoJson ビューアのサンプルは、MapItems の操作方法、ユーザー入力の処理方法、GeoJson ファイルとの入出力方法を示しています。
この例では、様々な MapItems を持つマップを表示します。MapItems は、QtLocation のGeoJsonData API を使って GeoJson ファイルからインポートされるか、TapHandlers を使ってユーザーによって描画される。
GeoJson ファイルの例は、example ディレクトリ内の data ディレクトリにある。
MapItem を描画するには、マップの何もない部分で右クリックし、表示されるメニューか ら好きなアイテムタイプを選択します。次のクリックで選択したアイテムが定義されます。この例では、MapCircles 、MapRectangles 、MapPolygons 、MapPolylines を描画することができます。2つの点で完全に定義されるアイテム、すなわち円や長方形は、マウスの左ボタンを2回クリックすることで描画されます。複数の点で定義されるアイテム、つまり多角形や多角形は、任意の量の左ボタンクリックで作成され、右ボタンで完了します。この方法で描かれたアイテムは、GeoJson 仕様に合うように、ポイント、ポリゴン、ポリラインとして保存されます。https://geojson.org/ を参照してください。
例の実行
Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。
MapView の作成
まず、すべてのアイテムを配置できるベースマップを作成します。基本的なMap と入力処理(マウスホイール、ドラッグなど)を組み合わせたMapView 要素を利用します。基礎となるMap は、map プロパティでアクセスできます。MapView のプロパティを見逃した場合は、MapView.map でアクセスできる可能性が高い。
MapView { id: view anchors.fill: parent map.plugin: Plugin { name: "osm" } map.zoomLevel: 4 map.center: QtPositioning.coordinate(3, 8) }
GeoJson モデルのセットアップ / MapItems の表示
ファイルの内容を地図上に表示するために、モデル/ビュープログラミングとして知られるデザインパターンを使用します。まず、適切なビュー、この例ではMapItemView 要素をセットアップする必要があります。その親は、MapView 、その中に配置されたすべてのアイテムを正しく表示するために、その下にあるマップに設定する必要があります。
MapItemView { id: miv parent: view.map }
次に、GeoJSONドキュメントを表す適切なモデルが必要です。この目的のために、QtLocation は GeoJSON ファイルを読み書きできるGeoJsonData 要素を提供しています。これは簡単にインスタンス化でき
GeoJsonData { id: geoDatabase sourceUrl: ":/data/11-full.json" }
MapItemViewに割り当てることができる。
model: geoDatabase.model
例として、11-full.json
ファイルが起動時に読み込まれる。
最後に、モデルデータをアイテムの表現に変換し、MapItemView を埋めるdelegate が必要です。
delegate: GeoJsonDelegate {}
GeoJsonDelegate
要素は、ファイルGeoJsonDelegate.qml
で宣言されます。これはDelegateChooser 要素であり、異なるジオメトリ・タイプのさまざまな特性を考慮に入れています。
DelegateChooser { id: dc role: "type" }
DelegateChooser には、GeoJson ファイルにあるジオメトリ タイプごとにDelegateChoice が含まれています。プロパティrole はDelegateChoice.roleValue と照合され、正しいデリゲートが決定されます。
例として、GeoJson の"type":"Point"
で記述された点は、MapItemView 上のMapCircle で表されます:
DelegateChoice { roleValue: "Point" delegate: MapCircle { property string geojsonType: "Point" property var props: modelData.properties geoShape: modelData.data radius: (props && props.radius) || 20*1000 border.width: 2 border.color: hh.hovered ? "magenta" : Qt.darker(color) opacity: dc.defaultOpacity color: (props && props.color) || (parent && parent.props && parent.props.color) || dc.defaultColor } }
color やradius のようなMapCircle のプロパティは、modelData プロパティの形で利用可能な GeoJson ファイルから読み込もうとします。しかし、これは GeoJson の厳密な標準ではなく、すべてのプロパティにフォールバック値が設定される。
GeoJson への MapItems の書き込み
MapItems を GeoJson ファイルに書き込むには、GeoJsonData::saveAs 関数を指定のファイル名で呼び出すだけです。これにより、現在のモデル内の全アイテムが指定されたファイルに書き込まれる。ファイルに書き込むべき他のアイテムは、まず関数GeoJsonData::addItem またはGeoJsonData::setModelToMapContents を使ってモデルに追加する必要がある。
geoDatabase.saveAs(fileWriteDialog.selectedFile)
MapItems とのユーザーインタラクション
ユーザーとのインタラクションを扱うために、PointHandlers を使います。MouseArea とは対照的に、MapItem は常に正方形の形状をカバーするので、このタスクに特に適しています。GeoJson ファイルからインポートされた MapItems は、デリゲート内で直接HoverHandler とTapHandler を取得します:
TapHandler { onTapped: { if (props !== undefined) console.log(props.name) else if (parent.parent.geojsonType == "MultiPoint") console.log(parent.parent.props.name) else console.log("NO NAME!", props) } } HoverHandler { id: hh }
TapHandler は、アイテムがタップされたときに、そのアイテムに関する情報をコンソールに書き込むた めに使用されます。HoverHandler は、マウスポインタの下にあるアイテムをハイライトするために使用されます。これは、HoverHandler のプロパティ / 状態hovered に応じてプロパティborder.color を記述することで実装されます。
新しいアイテムの追加
MapView のHoverHandler とTapHandler の組み合わせにより、ユーザーによるマウスの動きやクリックに反応することができます。
TapHandler がsingleTapped シグナルを発すると、LeftButton で新しい MapItem を作成または修正し、RightButton で MapItem を終了する。終了する項目がない場合は、RightButton でメニューを開く。
onSingleTapped: (eventPoint, button) => { lastCoordinate = view.map.toCoordinate(tapHandler.point.position) if (button === Qt.RightButton) { if (view.unfinishedItem !== undefined) { view.finishGeoItem() } else mapPopupMenu.show(lastCoordinate) } else if (button === Qt.LeftButton) { if (view.unfinishedItem !== undefined) { if (view.unfinishedItem.addGeometry(view.map.toCoordinate(tapHandler.point.position), false)) { view.finishGeoItem() } } } }
pointChanged シグナルは一時的に MapItem を更新し、ユーザーにプレビューを見せるために使われる。
HoverHandler { id: hoverHandler property variant currentCoordinate grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType onPointChanged: { currentCoordinate = view.map.toCoordinate(hoverHandler.point.position) if (view.unfinishedItem !== undefined) view.unfinishedItem.addGeometry(view.map.toCoordinate(hoverHandler.point.position), true) } }
Mapitems は別々の qml ファイルで定義されたプロトタイプから生成される。それらはcreateComponent 関数を使って作成され、addMapItem でマップに追加される。新しいアイテムへの参照は、ユーザーがさらに操作できるように保存される。
function addGeoItem(item) { var co = Qt.createComponent('mapitems/'+item+'.qml') if (co.status === Component.Ready) { unfinishedItem = co.createObject(map) unfinishedItem.setGeometry(tapHandler.lastCoordinate) unfinishedItem.addGeometry(hoverHandler.currentCoordinate, false) view.map.addMapItem(unfinishedItem) } else { console.log(item + " is not supported right now, please call us later.") } }
アイテムを表示するには、Map にアイテムを追加するだけで十分です。しかし、そのアイテムをさらに使う(例えば、ファイルに保存する)ためには、モデルに追加する必要がある。これは編集が終わった後に行われます:
function finishGeoItem() { unfinishedItem.finishAddGeometry() geoDatabase.addItem(unfinishedItem) map.removeMapItem(unfinishedItem) unfinishedItem = undefined }
アイテムの削除
マップからすべてのアイテムを削除するには、GeoJsonData オブジェクトのリセット関数を呼び出すだけです。
function clearAllItems() { geoDatabase.clear(); }
©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。