Learn how to find an address or place with a search bar and the geocoding service.
Geocoding is the process of converting address or place text into a location. The geocoding service can search for an address or a place and perform reverse geocoding.
In this tutorial, you use a search bar in the user interface to access the Geocoding service and search for addresses and places.
Prerequisites
Before starting this tutorial:
-
You need an ArcGIS Location Platform or ArcGIS Online account.
-
Your system meets the system requirements.
-
The ArcGIS Maps SDK for Qt, version 200.5.0 or later is installed.
-
The Qt 6.5.6 software development framework is installed.
Steps
Get an access token
You need an access token to use the location services used in this tutorial.
-
Go to the Create an API key tutorial to obtain an access token.
-
Ensure that the following privileges are enabled: Location services > Basemaps > Basemap styles service and Location services > Geocoding.
-
Copy the access token as it will be used in the next step.
To learn more about other ways to get an access token, go to Types of authentication.
Open the project in Qt Creator
-
To start this tutorial, complete the Display a map tutorial or download and unzip the solution.
-
Open the Display_a_map project in Qt Creator.
-
In the Projects window, in the Sources folder, open the main.cpp file.
-
Modify the code to set the API key to the access token. Save and close the file.
main.cppUse dark colors for code blocks // 2. API key authentication: Get a long-lived access token that gives your application access to // ArcGIS location services. Go to the tutorial at https://links.esri.com/create-an-api-key. // Copy the API Key access token. const QString accessToken = QString("");
Declare classes, member variables, functions, and signals
-
Double click on Sources > Display_a_map.h to open the file. Declare the classes shown.
Display_a_map.hUse dark colors for code blocks namespace Esri::ArcGISRuntime { class Map; class MapQuickView; class GraphicsOverlay; class Graphic; class LocatorTask; class GeocodeResult; class SuggestResult; class TextSymbol;
-
Add the following two
#include
statements.Display_a_map.hUse dark colors for code blocks } #include <QObject> Q_MOC_INCLUDE("MapQuickView.h") #include <QAbstractListModel> #include "GeocodeParameters.h"
-
Add a
Q
for the member variable_PROPERTY suggestions
.Display_a_map.hUse dark colors for code blocks class Display_a_map : public QObject { Q_OBJECT Q_PROPERTY(Esri::ArcGISRuntime::MapQuickView* mapView READ mapView WRITE setMapView NOTIFY mapViewChanged) Q_PROPERTY(QAbstractListModel* suggestions READ suggestions NOTIFY suggestionsChanged)
-
Add the following public member functions with the
Q
macro to allow these to be invokable from the GUI._INVOKABLE Display_a_map.hUse dark colors for code blocks public: explicit Display_a_map(QObject* parent = nullptr); ~Display_a_map() override; Q_INVOKABLE void geocode(const QString& query); Q_INVOKABLE void clearGraphics(); Q_INVOKABLE void setSuggestions(const QString& text);
-
Add two new signal declarations.
Display_a_map.hUse dark colors for code blocks signals: void mapViewChanged(); void suggestionsChanged(); void hideSuggestionView();
-
Declare the
setup
private method.Locator Task Display_a_map.hUse dark colors for code blocks private: Esri::ArcGISRuntime::MapQuickView* mapView() const; void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView); void setupViewpoint(); void setupLocatorTask();
-
Add the following six private member functions and variables. Then save and close the header file.
Display_a_map.hUse dark colors for code blocks void setupLocatorTask(); Esri::ArcGISRuntime::Map* m_map = nullptr; Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr; void configureGraphic(); QAbstractListModel* suggestions() const; Esri::ArcGISRuntime::GraphicsOverlay* m_graphicsOverlay = nullptr; Esri::ArcGISRuntime::LocatorTask* m_locatorTask = nullptr; Esri::ArcGISRuntime::Graphic* m_graphicResultLocation = nullptr; Esri::ArcGISRuntime::Graphic* m_graphicResultText = nullptr; Esri::ArcGISRuntime::TextSymbol* m_textSymbol = nullptr; QAbstractListModel* m_suggestListModel = nullptr; Esri::ArcGISRuntime::GeocodeParameters m_geocodeParams;
Include header files to access needed classes
-
In Projects, double click on Sources > Display_a_map.cpp to open the file and add the following
#include
statements.Display_a_map.cppUse dark colors for code blocks #include "Display_a_map.h" #include "Map.h" #include "MapTypes.h" #include "MapQuickView.h" #include "Point.h" #include "Viewpoint.h" #include "SpatialReference.h" #include <QFuture> #include "AttributeListModel.h" #include "Envelope.h" #include "GeocodeResult.h" #include "Graphic.h" #include "GraphicListModel.h" #include "GraphicsOverlay.h" #include "GraphicsOverlayListModel.h" #include "LocatorTask.h" #include "SimpleMarkerSymbol.h" #include "SimpleRenderer.h" #include "SymbolTypes.h" #include "SuggestParameters.h" #include "SuggestListModel.h" #include "TextSymbol.h"
-
Include the following Qt classes.
Display_a_map.cppUse dark colors for code blocks #include "AttributeListModel.h" #include "Envelope.h" #include "GeocodeResult.h" #include "Graphic.h" #include "GraphicListModel.h" #include "GraphicsOverlay.h" #include "GraphicsOverlayListModel.h" #include "LocatorTask.h" #include "SimpleMarkerSymbol.h" #include "SimpleRenderer.h" #include "SymbolTypes.h" #include "SuggestParameters.h" #include "SuggestListModel.h" #include "TextSymbol.h" #include <QAbstractListModel> #include <QGeoPositionInfoSource> #include <QUrl> #include <QUuid>
Create a locator task with geocode parameters
Geocoding is implemented with a locator, typically created by referencing a service such as the Geocoding service or, for offline geocoding, by referencing locator data contained in a mobile package. Geocoding parameters can be used to fine-tune the results, such as setting the maximum number of results or requesting additional attributes in the results.
-
Add the call to
setup
. This method will be implemented next.Locator Task Display_a_map.cppUse dark colors for code blocks Display_a_map::Display_a_map(QObject* parent /* = nullptr */): QObject(parent), m_map(new Map(BasemapStyle::ArcGISTopographic, this)) { setupLocatorTask();
-
Add code to begin implementing the
setup
method and initialize the auto-suggestion list. Within the method body, create a newLocator Task LocatorTask
based on the Geocoding service, and set it to them
member variable. Additionally, create a_locator Task SuggestParameters
, instance and initialize it with three categories as shown. Then set max results to limit for the number of returned suggestion results to 5. Finally, configureGeocodeParameters
, (m_geocodeParams). Add code to set the minimum match score and the attribute names for the results to be returned. Callsuggestions
onm
and assign to_locator Task m
._suggest List Model Display_a_map.cppUse dark colors for code blocks setupLocatorTask(); } Display_a_map::~Display_a_map() { } void Display_a_map::setupLocatorTask() { const QUrl geocode_service("https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer"); m_locatorTask = new LocatorTask(geocode_service, this); SuggestParameters suggestParams; const QStringList categories{"Address", "POI", "Populated Place"}; suggestParams.setCategories(categories); suggestParams.setMaxResults(5); m_locatorTask->suggestions()->setSuggestParameters(suggestParams); m_geocodeParams.setMinScore(75); m_geocodeParams.setResultAttributeNames(QStringList {"Place_addr", "Match_addr"}); m_suggestListModel = m_locatorTask->suggestions(); emit suggestionsChanged(); }
A locator task is used to convert an address to a point (geocode) or vice-versa (reverse geocode). An address includes any type of information that distinguishes a place. A locator involves finding matching locations for a given address. Reverse-geocoding is the opposite and finds the closest address for a given location.
Create the auto-suggestion feature
-
Add a new
set
method to implement the auto-suggestion feature. This generates a list of suggested addresses based on the user's input in the GUI text field.Suggestions Display_a_map.cppUse dark colors for code blocks setupViewpoint(); emit mapViewChanged(); } void Display_a_map::setSuggestions(const QString& text) { if (!m_suggestListModel) return; SuggestListModel* suggestListModel = dynamic_cast<SuggestListModel*>(m_suggestListModel); if (!suggestListModel) return; suggestListModel->setSearchText(text); }
-
Revise the
setup
method to respond to the user's mouse selection of an address from the list of suggested addresses. Inject the following code immediately after the open curly braces but before the other code in the function.Viewpoint Display_a_map.cppUse dark colors for code blocks void Display_a_map::setupViewpoint() { connect(m_mapView, &MapQuickView::mousePressed, this, [this](QMouseEvent& /* event */) { emit hideSuggestionView(); });
Add text and marker graphics to identify location on map
-
Add the call to
configure
, which will be implemented in the next step.Graphic Display_a_map.cppUse dark colors for code blocks const Point center(-118.80543, 34.02700, SpatialReference::wgs84()); const Viewpoint viewpoint(center, 100000.0); m_mapView->setViewpointAsync(viewpoint); configureGraphic();
-
Implement the
configure
public method. Create aGraphic SimpleMarkerSymbol
(blue square), initialize aGraphic
and add that to aGraphicsOverlay
. Then createTextSymbol
, initialize aGraphic
with that, and add it to theGraphicsOverlay
. Then add theGraphicsOverlay
toMapView
.Display_a_map.cppUse dark colors for code blocks if (!suggestListModel) return; suggestListModel->setSearchText(text); } void Display_a_map::configureGraphic() { if (m_graphicResultLocation) return; // create graphics overlay and add to map view m_graphicsOverlay = new GraphicsOverlay(this); // set a renderer on the graphics overlay SimpleRenderer* simpleRenderer = new SimpleRenderer(this); // Create a graphic and symbol to display the result location. SimpleMarkerSymbol* simpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Square, QColor("blue"), 12.0, this); simpleRenderer->setSymbol(simpleMarkerSymbol); m_graphicResultLocation = new Graphic(this); m_graphicResultLocation->setSymbol(simpleMarkerSymbol); m_graphicsOverlay->graphics()->append(m_graphicResultLocation); // Create a graphic and symbol to display a label next to the result location m_textSymbol = new TextSymbol("", QColor("red"), 18.0, HorizontalAlignment::Center, VerticalAlignment::Bottom, this); m_graphicResultText = new Graphic(this); m_graphicResultText->setSymbol(m_textSymbol); m_graphicsOverlay->graphics()->append(m_graphicResultText); m_mapView->graphicsOverlays()->append(m_graphicsOverlay); }
Add the Geocode method
An asynchronous geocode operation is required to find and return the location candidates for a given address and geocode parameters.
-
Add the
geocode
method to geocode an address when the user clicks on that address in the auto-suggestion list. This method will invoke the geocode with parameters async method on theLocatorTask
. Within the body of theif
statement, the code checks for geocoding results and verifies that the graphic exists. If both conditions are met, the result location is set as the graphic’s geometry and the attributes provided by the result are copied to the graphic. The map view display is centered on the graphic before making it visible. In the final block of code, the text symbol is set, the text graphic geometry for the geocoding result display location is set, the attributes for the text graphic is set, and graphic is made visible.Display_a_map.cppUse dark colors for code blocks m_graphicsOverlay->graphics()->append(m_graphicResultText); m_mapView->graphicsOverlays()->append(m_graphicsOverlay); } void Display_a_map::geocode(const QString& query) { m_locatorTask->geocodeWithParametersAsync(query, m_geocodeParams).then(this,[this](const QList<GeocodeResult>& geocodeResults) { if (!geocodeResults.isEmpty() && m_graphicResultLocation) { // display geocode result label and position const GeocodeResult geocodeResult = geocodeResults.at(0); m_graphicResultLocation->setGeometry(geocodeResult.displayLocation()); m_graphicResultLocation->attributes()->setAttributesMap(geocodeResult.attributes()); constexpr double scale = 8000.0; m_mapView->setViewpointCenterAsync(geocodeResult.extent().center(), scale); m_graphicResultLocation->setVisible(true); m_textSymbol->setText(geocodeResult.label()); m_graphicResultText->setGeometry(geocodeResult.displayLocation()); m_graphicResultText->attributes()->setAttributesMap(geocodeResult.attributes()); m_graphicResultLocation->setVisible(true); } }); }
-
Add the
suggestions
method to register the value ofm
as the value of the QML property_suggest List Model suggestions
.Display_a_map.cppUse dark colors for code blocks QAbstractListModel* Display_a_map::suggestions() const { return m_suggestListModel; }
-
Add the
clear
method. Then save and close the file.Graphics Display_a_map.cppUse dark colors for code blocks QAbstractListModel* Display_a_map::suggestions() const { return m_suggestListModel; } void Display_a_map::clearGraphics() { m_graphicResultLocation->setGeometry(Point()); m_graphicResultText->setGeometry(Point()); }
Create the application GUI
The GUI will let you enter partial or full addresses into a field, see a list of matching addresses, click an address and zoom to that location, and clear the address field.
-
In Projects, click on Resources > qml\qml.qrc > /qml. Then open the file Display_a_mapForm.qml
-
Add the following import statement.
Display_a_mapForm.qmlUse dark colors for code blocks import QtQuick import QtQuick.Controls import Esri.Display_a_map import QtQuick.Layouts
-
Change the
Map
componentView id
tosearch
.Display_a_mapForm.qmlUse dark colors for code blocks // Create MapQuickView here, and create its Map etc. in C++ code MapView { id: view anchors.fill: parent // set focus to enable keyboard navigation focus: true } // Declare the C++ instance that creates the map etc. and supply the view Display_a_map { id: search
-
Add the following QML code to implement the app GUI.
Display_a_mapForm.qmlUse dark colors for code blocks // Declare the C++ instance that creates the map etc. and supply the view Display_a_map { id: search mapView: view } Rectangle { // add rectangle for gui code id: searchRect width: parent.width height: childrenRect.height property int cellHeight: 40; Column { anchors { fill: parent margins: 10 } Rectangle { color: "#f7f8fa" border { color: "#7B7C7D" } radius: 2 width: parent.width height: childrenRect.height GridLayout { width: parent.width columns: 4 TextField { id: textField Layout.margins: 5 Layout.fillWidth: true font.pixelSize: 14 placeholderText: "Type in an address" selectByMouse: true onTextChanged: { if (text.length > 0 && suggestView) suggestView.visible = true; search.setSuggestions(text); } onAccepted: { suggestView.visible = false; search.geocode(textField.text); Qt.inputMethod.hide(); } } Rectangle { Layout.margins: 5 width: height height: textField.height color: "#f7f8fa" visible: textField.length === 0 enabled: visible Button { anchors.fill: parent text: "X" font.pixelSize: 16 MouseArea { anchors.fill: parent onClicked: { textField.focus = true; suggestView.visible = !suggestView.visible; } } } } Rectangle { Layout.margins: 5 width: height color: "transparent" height: textField.height visible: textField.length !== 0 enabled: visible Button { anchors.fill: parent text: "X" font.pixelSize: 16 MouseArea { anchors.fill: parent onClicked: { textField.text = ""; search.clearGraphics(); } } } } } } //Tutorial add ListView to display suggested location results and bind it to the locator task list model. ListView { id: suggestView height: 20 * searchRect.cellHeight width: textField.width model: search.suggestions visible: false clip: true delegate: Component { Rectangle { id: rect width: textField.width height: searchRect.cellHeight color: "#f7f8fa" Text { anchors { verticalCenter: parent.verticalCenter leftMargin: 5 rightMargin: 5 } font { weight: Font.Black pixelSize: 16 } width: textField.width text: label elide: Text.ElideRight color: "black" } MouseArea { anchors.fill: parent onClicked: { textField.text = label; suggestView.visible = false; search.geocode(label); Qt.inputMethod.hide(); } } } } } } }
Press Ctrl + R to run the app.
You should see a map centered on the Santa Monica Mountains in California, with an address search bar at the top. Input an address in the search bar and the app will present a list of suggested addresses (not limited to the displayed map area). Click an address to zoom to that address location.
What's next?
Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: