地点(QML)

地点示例演示了如何搜索地点并访问相关内容。

地点示例演示了如何搜索地点。特别是,它展示了如何检索更多信息,如评论、图片和相关信息。

运行示例

要从Qt Creator运行示例,请打开欢迎使用模式,然后从示例中选择示例。有关更多信息,请访问构建和运行示例

该示例可以与任何可用的地理服务插件一起工作。但是,某些插件可能需要额外的插件参数才能正确运行。可以使用具有以下形式的--plugin参数在命令行中传递插件参数

--plugin.<parameter name> <parameter value>

请参阅每个地理服务插件的文档,以了解它们支持哪些插件参数。本例默认使用的插件是Qt Location Open Street Map 插件,无需任何参数。

概述

地点示例显示一个应用程序窗口,其中包含一个地图。在窗口的顶部有一个搜索框,用于输入地点搜索查询。要搜索地点,请将搜索词输入到文本框中,然后单击放大镜图标。要按类别搜索地点,请单击类别图标以显示可用的类别列表并选择所需的类别。地点搜索查询将为地图上显示的当前位置附近的地点。

对于某些插件,当输入三个或更多字符时,搜索框会提供搜索词建议。选择其中一个建议将使用选择的搜索文本执行地点搜索。

单击搜索结果将显示有关地点的详细信息。如果地点有丰富的内容(评论、图片),可以通过详细信息页面上的按钮访问这些内容。要找到类似地点,请单击“查找类似地点”按钮。

可以通过访问“供应商”菜单来更改地理服务提供商。

显示类别

在进行按类别搜索之前,需要检索可用的类别列表。这是通过创建CategoryModel来实现的。

CategoryModel {
    id: categoryModel
    hierarchical: true
}

《CategoryModel》类型提供了可用类别的模型。它既可以提供平面列表,也可以提供层次树模型。在本例中,我们使用层次树模型,通过将“hierarchical”属性设置为true来实现。在示例初始化过程中设置了“plugin”属性。

接下来,我们创建一个ListView来显示类别模型。

ListView {
    id: root
    property var categoryModel
    property var rootIndex

    signal searchCategory(var category)
    signal showSubcategories(var index)

    snapMode: ListView.SnapToItem

    model: DelegateModel {
        id: delegeteDataModel
        model: root.categoryModel
        rootIndex: root.rootIndex
        delegate: CategoryDelegate {
            width: ListView.view.width
            onSearchCategory: root.searchCategory(category);
            onShowSubcategories: root.showSubcategories(delegeteDataModel.modelIndex(index));
        }
    }
}

由于正在使用层次模型,需要一个DelegateModel来提供导航功能。如果使用平面列表模型,视图可以直接使用CategoryModel

使用“rootIndex”属性设置“DelegateModel”的根索引。类别是通过“CategoryDelegate”显示的,它提供了两个信号。当选择类别后,onShowSubcategories发出带有根索引的showSubcategories()信号,将当前索引的下级类别显示出来。当执行搜索时,onSearchCategory处理程序会发出带有类别参数的searchCategory()信号,以指示已选择哪个特定类别。

当点击Label时,CategoryDelegate会显示类别名称并发出searchCategory()信号。

Label {
    id: labelItem
    text: category.name
    anchors.left: icon.right
    anchors.right: parent.right
    anchors.verticalCenter: parent.verticalCenter
}

TapHandler {
    id: tapHanlder
    onTapped: {
        if (model.hasModelChildren) {
            root.showSubcategories()
        } else {
            root.searchCategory()
        }
    }
}

呈现搜索建议

使用PlaceSearchSuggestionModel类型来根据部分输入的搜索词获取建议搜索词。

只要输入的搜索词发生变化,就会触发新的建议搜索。

SearchBar {
    id: searchBar
    onSearchTextChanged: function (searchText) {
        if (searchText.length >= 3 && suggestionModel != null) {
            suggestionModel.searchTerm = searchText;
            suggestionModel.update();
        }
    }
}

只有当搜索词长度为三个或更多字符时,才会查询建议。

PlaceSearchSuggestionModel的状态发生变化时,搜索建议会显示出来。

PlaceSearchSuggestionModel {
    id: suggestionModel
    searchArea: searchRegion

    onStatusChanged: {
        if (status == PlaceSearchSuggestionModel.Ready)
            stackView.showSuggestions()
    }
}

“SuggestionsShown”状态中的主要对象是ListView,用于显示搜索建议。

ListView {
    id: suggestionView
    property var suggestionModel
    signal suggestionSelected(string text)

    model: suggestionModel
    delegate: Item {
        width: ListView.view.width
        height: label.height * 1.5
        Label {
            id: label
            text: suggestion
        }
        MouseArea {
            anchors.fill: parent
            onClicked: suggestionSelected(suggestion)
        }
    }
}

使用Label对象作为代理来显示建议文本。单击建议搜索词将更新搜索词并触发使用搜索建议的地方搜索。

搜索地点

使用PlaceSearchModel类型来搜索地点。

PlaceSearchModel {
    id: placeSearchModel
    searchArea: searchRegion

    function searchForCategory(category) {
        searchTerm = "";
        categories = category;
        recommendationId = "";
        searchArea = searchRegion
        limit = -1;
        update();
    }

    function searchForText(text) {
        searchTerm = text;
        categories = null;
        recommendationId = "";
        searchArea = searchRegion
        limit = -1;
        update();
    }

    function searchForRecommendations(placeId) {
        searchTerm = "";
        categories = null;
        recommendationId = placeId;
        searchArea = null;
        limit = -1;
        update();
    }

    onStatusChanged: {
        switch (status) {
        case PlaceSearchModel.Ready:
            if (count > 0)
                stackView.showPlaces()
            else
                stackView.showMessage(qsTr("Search Place Error"),qsTr("Place not found !"))
            break;
        case PlaceSearchModel.Error:
            stackView.showMessage(qsTr("Search Place Error"),errorString())
            break;
        }
    }
}

首先设置了模型的一些属性,这些属性将用于形成搜索请求。将搜索区域的“searchArea”属性设置为具有geocircle中心的对象,该中心链接到在Map上显示的当前位置。

最后,我们定义了三个辅助函数searchForCategory()searchForText()searchForRecommendations(),它们设置categoriessearchTermrecommendationId属性,并调用update()方法开始地点搜索。搜索结果在ListView中显示。

ListView {
    id: searchView

    property var placeSearchModel
    signal showPlaceDetails(var place, var distance)
    signal showMap()

    model: placeSearchModel
    delegate: SearchResultDelegate {
        width: ListView.view.width
        onShowPlaceDetails: function (place, distance) { searchView.showPlaceDetails(place, distance) }
        onSearchFor: function (query) { placeSearchModel.searchForText(query) }
    }

    footer: RowLayout {
        width: parent.width

        Button {
            text: qsTr("Previous")
            enabled: placeSearchModel.previousPagesAvailable
            onClicked: placeSearchModel.previousPage()
            Layout.alignment: Qt.AlignHCenter
        }

        Button {
            text: qsTr("Clear")
            onClicked: {
                placeSearchModel.reset()
                showMap()
            }
            Layout.alignment: Qt.AlignHCenter
        }

        Button {
            text: qsTr("Next")
            enabled: placeSearchModel.nextPagesAvailable
            onClicked: placeSearchModel.nextPage()
            Layout.alignment: Qt.AlignHCenter
        }
    }
}

ListView中所使用的代理SearchResultDelegate通过Loader对象设计来处理多种搜索结果类型。对PlaceResult类型的搜索结果,代理是

Component {
    id: placeComponent
    Item {
        id: placeRoot
        width: root.width
        height: Math.max(icon.height, 3 * placeName.height)

        Rectangle {
            anchors.fill: parent
            color: "#44ffffff"
            visible: mouse.pressed
        }

        Rectangle {
            anchors.fill: parent
            color: "#dbffde"
            visible: model.sponsored !== undefined ? model.sponsored : false

            Label {
                text: qsTr("Sponsored result")
                horizontalAlignment: Text.AlignRight
                anchors.right: parent.right
                anchors.bottom: parent.bottom
                font.pixelSize: 8
                visible: model.sponsored !== undefined ? model.sponsored : false
            }
        }

        GridLayout {
            rows: 2
            columns: 2
            anchors.fill: parent
            anchors.leftMargin: 30
            flow: GridLayout.TopToBottom

            Image {
                // anchors.verticalCenter: parent.verticalCenter
                id:icon
                source: place.favorite ? Qt.resolvedUrl("../resources/star.png") : place.icon.url()
                Layout.rowSpan: 2
            }

            Label {
                id: placeName
                text: place.favorite ? place.favorite.name : place.name
                Layout.fillWidth: true
            }

            Label {
                id: distanceText
                font.italic: true
                text: Helper.formatDistance(distance)
                Layout.fillWidth: true
            }
        }

        Rectangle {
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.margins: 15
            height: 1
            color: "#46a2da"
        }

        MouseArea {
            id: mouse
            anchors.fill: parent
            onClicked: {
                if (model.type === undefined || type === PlaceSearchModel.PlaceResult) {
                    if (!place.detailsFetched)
                        place.getDetails();
                    root.showPlaceDetails(model.place, model.distance);
                }
            }
        }
    }
}

显示地点内容

地点可以拥有额外的丰富内容,包括评论、评价和图片。丰富内容通过一组模型进行访问。通常,应用开发者不会直接创建内容模型,而是从editorialModelreviewModelimageModel属性获取模型,这些属性属于Place类型。

ListView {
    id:view
    property Place place
    signal showEditorial(var editorial)
    model: place.editorialModel
    delegate: EditorialDelegate {
        width: ListView.view.width
        onShowEditorial: view.showEditorial(model)
    }
}

示例项目 @ code.qt.io

© 2024 Qt公司有限公司。此处包含的文档贡献属于各自所有者的版权。此处提供的文档根据自由软件基金会发布的GNU自由文档许可1.3版的条款进行许可。Qt及其相关标志是芬兰和/或其他国家/地区Qt公司有限公司的商标。所有其他商标均为各自所有者的财产。