GeoJson ビューア (QML)
GeoJson ビューアのサンプルでは、MapItem の操作方法、ユーザー入力の処理、および GeoJson ファイルとの間でデータを出し入れする方法を示しています。

このサンプルでは、さまざまな MapItem を含む地図が表示されます。MapItem は、QtLocation のGeoJsonData API を使用して GeoJson ファイルからインポートされるか、TapHandlers を使用してユーザーによって描画されます。
GeoJSONファイルの例は、例題ディレクトリ内の「data」ディレクトリにあります。
MapItemを描画するには、地図の何もない部分を右クリックし、表示されるメニューから任意のアイテムタイプを選択します。その後のクリックで、選択したアイテムを定義します。この例では、MapCircles 、MapRectangles 、MapPolygons 、およびMapPolylines を描画することができます。2つの点で完全に定義されるアイテム(円や長方形など)は、マウスの左ボタンを2回クリックして描画します。 複数の点によって定義される図形(多角形やポリラインなど)は、左ボタンを任意の回数クリックして作成し、右ボタンで完了させます。この方法で描画された図形は、GeoJSON仕様に準拠するように点、多角形、ポリラインとして保存されます。詳細は https://geojson.org/ を参照してください。
例の動作
以下の手順でサンプルを実行できます。
- Qt Creator
Welcome モードを開き、Examples からこの例を選択してください。詳細については、Qt Creator の「チュートリアル:ビルドと実行」を参照してください。
- Qt Extension for Visual Studio Code
Command Palette から「Qt: Open Qt examples 」コマンドを実行し、リストから例を選択します。詳細については、Qt Extension for Visual Studio Code の「チュートリアル:ビルドと実行」を参照してください。
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
}
}MapCircle のプロパティ(color やradius など)は、modelData プロパティとして利用可能な GeoJSON ファイルから読み込まれます。ただし、これは GeoJSON の厳密な標準ではなく、すべてのプロパティに対してフォールバック値が設定されています。
MapItemsをGeoJSONに書き込む
MapItemsをGeoJSONファイルに書き込むには、指定したファイル名を引数としてGeoJsonData::saveAs 関数を呼び出すだけで済みます。これにより、現在のモデル内のすべてのアイテムが指定されたファイルに書き込まれます。ファイルに書き込む必要があるその他のアイテムについては、まずGeoJsonData::addItem またはGeoJsonData::setModelToMapContents 関数を使用してモデルに追加する必要があります。
geoDatabase.saveAs(fileWriteDialog.selectedFile)MapItems とのユーザーインタラクション
ユーザー操作を処理するには、PointHandlers を使用します。これらは、常に正方形の形状を覆うMouseArea とは対照的に、基になるアイテムの正確な形状に準拠しているため、このタスクに特に適しています。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)
}
}MapItemは、個別の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 オブジェクトのreset関数を呼び出すだけです。
function clearAllItems()
{
geoDatabase.clear();
}© 2026 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.