GeoJson 뷰어(QML)

GeoJson 뷰어 예제에서는 MapItems을 조작하고 사용자 입력 및 GeoJson 파일과의 입출력을 처리하는 방법을 보여 줍니다.

이 예제에서는 다양한 MapItem이 있는 맵을 표시합니다. MapItems는 QtLocationGeoJsonData API를 사용하여 GeoJson 파일에서 가져오거나 TapHandlers 를 사용하여 사용자가 그립니다.

GeoJson 파일의 예는 예제 디렉터리 내의 디렉토리 데이터에서 찾을 수 있습니다.

MapItem을 그리려면 지도의 빈 부분을 마우스 오른쪽 버튼으로 클릭하고 표시되는 메뉴에서 원하는 항목 유형을 선택합니다. 다음에 클릭하면 선택한 항목이 정의됩니다. 이 예에서는 MapCircles, MapRectangles, MapPolygons, MapPolylines 을 그릴 수 있습니다. 원과 직사각형 등 두 개의 점으로 완전히 정의된 항목은 마우스 왼쪽 버튼을 두 번 클릭하면 그려집니다. 다각형 및 폴리라인과 같이 여러 점으로 정의된 항목은 임의의 왼쪽 버튼 클릭으로 생성되고 마우스 오른쪽 버튼으로 완성됩니다. 이렇게 그려진 항목은 GeoJson 사양에 맞게 점, 다각형 및 폴리라인으로 저장됩니다( https://geojson.org/ 참조).

예제 실행하기

에서 예제를 실행하려면 Qt Creator에서 Welcome 모드를 열고 Examples 에서 예제를 선택합니다. 자세한 내용은 예제 작성 및 실행을 참조하세요.

맵뷰 만들기

먼저 모든 항목을 배치할 수 있는 기본 맵을 만듭니다. 기본 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 모델 설정/맵 항목 표시하기

맵에 파일 내용을 표시하기 위해 모델/보기 프로그래밍이라는 디자인 패턴을 사용합니다. 먼저 적절한 보기(이 예에서는 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 의 속성은 모델데이터 속성의 형태로 제공되는 GeoJson 파일에서 읽으려고 시도됩니다. 그러나 이것은 GeoJson의 엄격한 표준이 아니며 모든 속성에 대해 대체 값이 설정됩니다.

MapItems를 GeoJson에 쓰기

지정된 파일명을 사용하여 GeoJsonData::saveAs 함수를 호출하면 MapItems를 GeoJson 파일에 쓸 수 있습니다. 그러면 현재 모델의 모든 항목이 지정된 파일에 기록됩니다. 파일에 기록해야 하는 다른 모든 항목은 GeoJsonData::addItem 또는 GeoJsonData::setModelToMapContents 함수를 사용하여 먼저 모델에 추가해야 합니다.

geoDatabase.saveAs(fileWriteDialog.selectedFile)

맵항목과 사용자 상호작용

사용자 상호작용을 처리하기 위해 PointHandlers 을 사용합니다. 이 함수는 항상 정사각형 모양을 다루는 MouseArea 과 달리 기본 항목의 정확한 모양을 따르기 때문에 이 작업에 특히 적합합니다. GeoJson 파일에서 가져온 맵 항목은 델리게이트에서 직접 자체 HoverHandlerTapHandler 을 가져옵니다:

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 속성을 설명하는 방식으로 구현됩니다.

새 항목 추가하기

MapViewHoverHandlerTapHandler 을 조합하면 사용자의 마우스 움직임과 클릭에 반응할 수 있습니다.

TapHandler 에서 singleTapped 신호를 보내면 LeftButton 에서 새 맵아이템을 생성하거나 수정하고 RightButton 에서 맵아이템을 완료합니다. 완료할 항목이 없는 경우 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 신호는 맵아이템을 일시적으로 업데이트하여 사용자에게 미리보기를 제공하는 데 사용됩니다.

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)
    }
}

맵아이템은 별도의 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();
}

예제 프로젝트 @ code.qt.io

© 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.