Places (QML)
「Places」のサンプルでは、場所を検索し、関連コンテンツにアクセスする方法を示しています。

「Places」サンプルでは、場所の検索方法を示しています。特に、レビュー、画像、関連コンテンツなどの詳細情報を取得する方法を説明しています。
例の動作確認
以下の場所からサンプルを実行できます:
- Qt Creator
Welcome モードを開き、Examples からサンプルを選択します。詳細については、Qt Creator の「チュートリアル:ビルドと実行」を参照してください。
- Qt Extension for Visual Studio Code
Command Palette から `Qt: Open Qt examples ` コマンドを実行し、リストからサンプルを選択します。詳細については、Qt Extension for Visual Studio Code の「チュートリアル:ビルドと実行」を参照してください。```
このサンプルは、利用可能などのジオサービスプラグインでも動作します。ただし、一部のプラグインでは、正しく機能するために追加のplugin parameters が必要になる場合があります。Plugin parameters は、--plugin 引数を使用してコマンドラインから指定できます。その形式は以下の通りです:
--plugin.<parameter name> <parameter value>各ジオサービスプラグインがサポートするパラメータの詳細については、各プラグインのドキュメントを参照してください。この例で使用されるデフォルトのプラグインは「Qt Location Open Street Map Plugin」であり、このプラグインにはパラメータは不要です。
概要
「Places」のサンプルでは、地図を表示するアプリケーションウィンドウが表示されます。ウィンドウの上部には検索ボックスがあり、場所の検索クエリを入力するために使用します。 場所を検索するには、テキストボックスに検索語句を入力し、虫眼鏡アイコンをクリックします。カテゴリ別に場所を検索するには、カテゴリアイコンをクリックして利用可能なカテゴリの一覧を表示し、目的のカテゴリを選択します。場所の検索クエリは、地図上に表示されている現在地付近の場所を対象とします。
一部のプラグインでは、検索ボックスに 3 文字以上入力すると、検索語の候補が表示されます。候補のいずれかを選択すると、選択した検索語を使用して場所の検索が行われます。
検索結果をクリックすると、その場所の詳細が表示されます。場所に豊富なコンテンツ(記事、レビュー、画像など)がある場合は、詳細ページのボタンからそれらにアクセスできます。類似の場所を探すには、「類似の場所を探す」ボタンをクリックしてください。
「プロバイダー」メニューから、地理情報サービスプロバイダーを変更できます。
カテゴリの表示
カテゴリによる検索を実行するには、まず利用可能なカテゴリのリストを取得する必要があります。これは、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 によって表示され、このデリゲートは 2 つのシグナルを提供します。onShowSubcategoriesは、ルートインデックスから現在のインデックスまでの範囲を示すshowSubcategories()シグナルを発行し、これにより選択されたカテゴリのサブカテゴリが表示されます。onSearchCategoryハンドラは、どの特定のカテゴリが選択されたかを示すカテゴリパラメータを伴ったsearchCategory()シグナルを発行します。
CategoryDelegateは、Label がクリックされた際に、カテゴリ名を表示し、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();
}
}
}検索語の長さが3文字以上の場合にのみ、候補が取得されます。
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 」プロパティには、「searchRegion」オブジェクトが設定されます。これは、Map に表示されている現在の位置にリンクされた中心を持つ「geoCircle 」です。
最後に、3つのヘルパー関数`searchForCategory()`、`searchForText()`、および`searchForRecommendations()` を定義します。これらは、`categories `、`searchTerm `、または `recommendationId ` プロパティのいずれかを設定し、`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);
}
}
}
}
}場所コンテンツの表示
Placeには、記事、レビュー、画像などの追加のリッチコンテンツが含まれる場合があります。リッチコンテンツへのアクセスは、一連のモデルを介して行われます。コンテンツモデルは通常、アプリケーション開発者が直接作成するものではなく、Place 型のeditorialModel 、reviewModel 、およびimageModel プロパティから取得されます。
© 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.