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
The following are required for this tutorial:
- An ArcGIS account to access API keys. If you don't have an account, sign up for free.
- Your system meets the system requirements.
- The ArcGIS Maps SDK for Qt, version 200.4.0 or later is installed.
- The Qt 6.5.1 software development framework is installed.
Steps
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.
-
If you downloaded the Display a map solution, set your API key.
An API Key enables access to services, web maps, and web scenes hosted in ArcGIS Online.
-
Go to your developer dashboard to get your API key. For these tutorials, use your default API key. It is scoped to include all of the services demonstrated in the tutorials.
-
In the Projects window, in the Sources folder, open the main.cpp file.
-
Modify the code to set the API key. Paste the API key, acquired from your dashboard, between the quotes. Then save and close the file.
main.cppUse dark colors for code blocks Change line // 2. API key authentication: Get a permanent key that gives your application access to Esri // location services. Create a new API key or access existing API keys from // your ArcGIS for Developers dashboard (https://links.esri.com/arcgis-api-keys). const QString apiKey = 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 Add line. Add line. Add line. Add line. Add line. Add line. 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 Add line. Add line. } #include <QObject> Q_MOC_INCLUDE("MapQuickView.h") #include <QAbstractListModel> #include "GeocodeParameters.h"
-
Add a
Q_
for the member variablePROPERTY suggestions
.Display_a_map.hUse dark colors for code blocks Add line. 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 Add line. Add line. Add line. 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 Add line. Add line. signals: void mapViewChanged(); void suggestionsChanged(); void hideSuggestionView();
-
Declare the
setup
private method.Locator Task Display_a_map.hUse dark colors for code blocks Add line. 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 Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 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 Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. #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 Add line. Add line. Add line. Add line. #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 Add line. 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
with the Geocoding service URL, and set it to them_
member variable. Additionally, create alocator 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 tolocator Task m_
.suggest List Model Display_a_map.cppUse dark colors for code blocks Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 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 Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 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.Viewpoint Display_a_map.cppUse dark colors for code blocks Add line. Add line. Add line. Add line. 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 Add line. 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 Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 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 Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. 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 propertysuggest List Model suggestions
.Display_a_map.cppUse dark colors for code blocks Add line. Add line. Add line. Add line. 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 Add line. Add line. Add line. Add line. Add line. 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 Add line. 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 Change line // 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 Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. // 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 leftPadding: 5 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: