Learn how to apply renderers and label definitions to a feature layer based on attribute values.
Applications can display feature layer data with different styles to enhance the visualization. The type of Renderer
you choose depends on your application. A SimpleRenderer
applies the same symbol to all features, a UniqueValueRenderer
applies a different symbol to each unique attribute value, and a ClassBreaksRenderer
applies a symbol to a range of numeric values. Renderers are responsible for accessing the data and applying the appropriate symbol to each feature when the layer draws. You can also use a LabelDefinition
to show attribute information for features. Visit the Styles and data visualization documentation to learn more about styling layers.
You can also author, style and save web maps, web scenes, and layers as portal items and then add them to the map in your application. Visit the following tutorials to learn more about adding portal items.
In this tutorial, you will apply different renderers to enhance the visualization of three feature layers with data for the Santa Monica Mountains: Trailheads with a single symbol, Trails based on elevation change and bike use, and Parks and Open Spaces based on the type of park.
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.6.0 or later is installed.
-
The Qt 6.5.6 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 solution, get an access token and set the API key.
An API Key gives your app access to secure resources used in this tutorial.
-
Go to the Create an API key tutorial to obtain a new API key access token. Ensure that the following privilege is enabled: Location services > Basemaps > Basemap styles service. Copy the access token as it will be used in the next step.
-
In the Projects window, in the Sources folder, open the main.cpp file.
-
Modify the code to set the API key to the copied 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("");
-
Add needed classes and declarations
-
In the Projects window, open the Headers folder. Open the Display_a_map.h file.
-
Add the
LabelDefinition
andFeatureLayer
classes to the namespace.Display_a_map.hUse dark colors for code blocks namespace Esri::ArcGISRuntime { class Map; class MapQuickView; class LabelDefinition; class FeatureLayer;
-
Add the declarations for methods you will create.
Display_a_map.hUse dark colors for code blocks private: Esri::ArcGISRuntime::MapQuickView* mapView() const; void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView); void setupViewpoint(); void addOpenSpaceLayer(); void addTrailsLayer(); void addNoBikeTrailsLayer(); void addBikeOnlyTrailsLayer(); void addTrailheadsLayer(); Esri::ArcGISRuntime::FeatureLayer* addFeatureLayer(const QUrl& url); Esri::ArcGISRuntime::LabelDefinition* makeLabelDefinition();
-
Save and close the file.
Create a function to add a feature layer
A feature layer can be added from a feature service hosted in ArcGIS Online. Each feature layer contains features with a single geometry type (point, line, or polygon), and a set of attributes. Once added to the map, feature layers can be symbolized, styled, and labeled in a variety of ways.
Next, you will create a helper method to add a layer to the map's collection of operational layers. You will use this helper method throughout the tutorial as you add and symbolize various layers.
-
Add include statements to access the classes that will be used.
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 "SpatialReference.h" #include <QFuture> #include "Viewpoint.h" #include "FeatureLayer.h" #include "ServiceFeatureTable.h" #include "LayerListModel.h"
-
Add a helper method named
add
that takes a feature service URL as an argument.Feature Layer() Display_a_map.cppUse dark colors for code blocks void Display_a_map::setupViewpoint() { const Point center(-118.80543, 34.02700, SpatialReference::wgs84()); const Viewpoint viewpoint(center, 100000.0); m_mapView->setViewpointAsync(viewpoint); } // Create a new function that creates a feature layer and appends it to the operational layers and the m_map. FeatureLayer* Display_a_map::addFeatureLayer(const QUrl& url) { ServiceFeatureTable* serviceFeatureTable = new ServiceFeatureTable(url, this); FeatureLayer* featureLayer = new FeatureLayer(serviceFeatureTable, this); m_map->operationalLayers()->append(featureLayer); return featureLayer; }
Add a layer with a unique value renderer
Create a method that creates a variable to store a feature service URL. Create a Parks and Open Spaces feature layer using that variable and then apply a different symbol for each type of park area displayed.
-
Add include statements to access the classes that will be used.
Display_a_map.cppUse dark colors for code blocks #include "FeatureLayer.h" #include "ServiceFeatureTable.h" #include "LayerListModel.h" #include "SymbolTypes.h" #include "UniqueValue.h" #include <QUrl> #include "SimpleFillSymbol.h" #include "UniqueValueRenderer.h"
-
Add a new method named
add
, after the newly addedOpen Space Layer() add
method.Feature Layer() Display_a_map.cppUse dark colors for code blocks void Display_a_map::addOpenSpaceLayer() { // Create a parks and open spaces feature layer. QUrl parksAndOpenSpacesQUrl("https://services3.arcgis.com/GVgbJbqm8hXASVYi/ArcGIS/rest/services/Parks_and_Open_Space/FeatureServer/0"); FeatureLayer* featureLayer = addFeatureLayer(parksAndOpenSpacesQUrl); // Create fill symbols. SimpleFillSymbol* purpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor("purple"), this); SimpleFillSymbol* greenFillSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor("green"), this); SimpleFillSymbol* blueFillSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor("blue"), this); SimpleFillSymbol* redFillSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor("red"), this); // Create a unique value for natural areas, regional open spaces, local parks & regional recreation parks. UniqueValue* naturalAreas = new UniqueValue("Natural Areas", "Natural Areas", {"Natural Areas"}, purpleFillSymbol, this); UniqueValue* regionalOpenSpace = new UniqueValue("Regional Open Space", "Regional Open Space", {"Regional Open Space"}, greenFillSymbol, this); UniqueValue* localPark = new UniqueValue("Local Park", "Local Park", {"Local Park"}, blueFillSymbol, this); UniqueValue* regionalRecreationPark = new UniqueValue("Regional Recreation Park", "Regional Recreation Park", {"Regional Recreation Park"}, redFillSymbol, this); // Create and assign a unique value renderer to the feature layer. UniqueValueRenderer* openSpacesUniqueValueRenderer = new UniqueValueRenderer("Open Spaces", nullptr, {"TYPE"}, {naturalAreas, regionalOpenSpace, localPark, regionalRecreationPark }, this); featureLayer->setRenderer(openSpacesUniqueValueRenderer); // Set the layer opacity to semi-transparent. featureLayer->setOpacity(0.25f); }
-
Update
setup
to call the newViewpoint() add
method.Open Space Layer() Display_a_map.cppUse dark colors for code blocks void Display_a_map::setupViewpoint() { const Point center(-118.80543, 34.02700, SpatialReference::wgs84()); const Viewpoint viewpoint(center, 100000.0); m_mapView->setViewpointAsync(viewpoint); addOpenSpaceLayer();
-
Press Ctrl + R to run the app.
When the app opens, Parks and Open Spaces feature layer is added to the map. The map displays the different types of parks and open spaces with four unique symbols.
Add a layer with a class breaks renderer
Create a method to apply a different symbol for each of the five ranges of elevation gain to the Trails feature layer.
-
Add include statements to access the classes that will be used.
Display_a_map.cppUse dark colors for code blocks #include "SymbolTypes.h" #include "UniqueValue.h" #include <QUrl> #include "SimpleFillSymbol.h" #include "UniqueValueRenderer.h" #include "SimpleLineSymbol.h" #include <QList> #include "ClassBreaksRenderer.h"
-
Add a global QUrl variable for the trails feature service.
Display_a_map.cppUse dark colors for code blocks MapQuickView* Display_a_map::mapView() const { return m_mapView; } QUrl trailsQUrl("https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0");
-
Add a new method named
add
.Trails Layer() A
ClassBreak
assigns a symbol to a range of values.For this example, the renderer uses each feature's
ELEV
attribute value to classify it into a defined range (class break) and apply the corresponding symbol._GAIN Display_a_map.cppUse dark colors for code blocks void Display_a_map::addTrailsLayer() { FeatureLayer* featureLayer = addFeatureLayer(trailsQUrl); // Create five line symbols to display class breaks. SimpleLineSymbol* firstClassSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("purple"), 3, this); SimpleLineSymbol* secondClassSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("purple"), 4, this); SimpleLineSymbol* thirdClassSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("purple"), 5, this); SimpleLineSymbol* fourthClassSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("purple"), 6, this); SimpleLineSymbol* fifthClassSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("purple"), 7, this); // Create five class breaks. ClassBreak* firstClassBreak = new ClassBreak("Under 500", "0 - 500", 0.0, 500.0, firstClassSymbol, this); ClassBreak* secondClassBreak = new ClassBreak("501 to 1000", "501 - 1000", 501.0, 1000.0, secondClassSymbol, this); ClassBreak* thirdClassBreak = new ClassBreak("1001 to 1500", "1001 - 1500", 1001.0, 1500.0, thirdClassSymbol, this); ClassBreak* fourthClassBreak = new ClassBreak("1501 to 2000", "1501 - 2000", 1501.0, 2000.0, fourthClassSymbol, this); ClassBreak* fifthClassBreak = new ClassBreak("2001 to 2300", "2001 to 2300", 2001.0, 2300.0, fifthClassSymbol, this); QList<ClassBreak*> elevationBreaks = {firstClassBreak, secondClassBreak, thirdClassBreak, fourthClassBreak, fifthClassBreak}; // Create and assign a class breaks renderer to the feature layer. ClassBreaksRenderer* elevationClassBreaksRenderer = new ClassBreaksRenderer("ELEV_GAIN", elevationBreaks, this); featureLayer->setRenderer(elevationClassBreaksRenderer); // Set the layer opacity to semi-transparent. featureLayer->setOpacity(0.75); }
-
Update
setup
to call the newViewpoint() add
method.Trails Layer() Display_a_map.cppUse dark colors for code blocks void Display_a_map::setupViewpoint() { const Point center(-118.80543, 34.02700, SpatialReference::wgs84()); const Viewpoint viewpoint(center, 100000.0); m_mapView->setViewpointAsync(viewpoint); addOpenSpaceLayer(); addTrailsLayer();
-
Press Ctrl + R to run the app.
When the app opens, the Trails feature layer is added to the map. The map displays trails with different symbols depending on trail elevation.
Add layers that leverage definition expressions
You can use a definition expression to define a subset of features to display. Features that do not meet the expression criteria are not displayed by the layer. In the following steps, you will create two methods that use a definition expression to apply a symbol to a subset of features in the Trails feature layer.
FeatureLayer::definitionExpression()
uses a SQL expression to limit the features available for query and display. Your code will create two layers that each display a different subset of trails based on the value for the USE
field. Trails that allow bikes will be symbolized with a blue symbol ("
) and those that don't will be red ("
). Another way to symbolize these features would be to create a UniqueValueRenderer
that applies a different symbol for these values.
-
Add the include statement to access the additional class that will be used.
Display_a_map.cppUse dark colors for code blocks #include "SymbolTypes.h" #include "UniqueValue.h" #include <QUrl> #include "SimpleFillSymbol.h" #include "UniqueValueRenderer.h" #include "SimpleLineSymbol.h" #include <QList> #include "ClassBreaksRenderer.h" #include "SimpleRenderer.h"
-
Add a method named
add
with a definition expression to filter for trails that permit bikes.Bike Only Trails Layer() Display_a_map.cppUse dark colors for code blocks void Display_a_map::addBikeOnlyTrailsLayer() { // Create a trails feature layer and add it to the map view. FeatureLayer* featureLayer = addFeatureLayer(trailsQUrl); // Write a definition expression to filter for trails that permit the use of bikes. featureLayer->setDefinitionExpression("USE_BIKE = 'Yes'"); // Create and assign a simple renderer to the feature layer. SimpleLineSymbol* bikeTrailSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Dot, QColor("blue"), 2, this); SimpleRenderer* bikeTrailRenderer = new SimpleRenderer(bikeTrailSymbol, this); featureLayer->setRenderer(bikeTrailRenderer); }
-
Add another method named
add
with a definition expression to filter for trails that don't allow bikes.No Bike Trails Layer() Display_a_map.cppUse dark colors for code blocks void Display_a_map::addNoBikeTrailsLayer() { // Create a trails feature layer and add it to the map view. FeatureLayer* featureLayer = addFeatureLayer(trailsQUrl); // Write a definition expression to filter for trails that don't permit the use of bikes. featureLayer->setDefinitionExpression("USE_BIKE = 'No'"); // Create and assign a simple renderer to the feature layer. SimpleLineSymbol* noBikeTrailSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Dot, QColor("red"), 2, this); SimpleRenderer* noBikeTrailRenderer = new SimpleRenderer(noBikeTrailSymbol, this); featureLayer->setRenderer(noBikeTrailRenderer); }
-
Update
setup
to call the newViewpoint() add
andBike Only Trails Layer() add
methods.No Bike Trails Layer() Display_a_map.cppUse dark colors for code blocks void Display_a_map::setupViewpoint() { const Point center(-118.80543, 34.02700, SpatialReference::wgs84()); const Viewpoint viewpoint(center, 100000.0); m_mapView->setViewpointAsync(viewpoint); addOpenSpaceLayer(); addTrailsLayer(); addBikeOnlyTrailsLayer(); addNoBikeTrailsLayer();
-
Press Ctrl + R to run the app.
When the app opens, two Trails feature layers are added to the map. One shows where bikes are permitted and the other where they are prohibited.
Symbolize a layer with a picture symbol and label features with an attribute
Create a method to style trailheads with hiker images and labels for the Trailheads feature layer.
-
Add the include statement to access the additional classes that will be used.
Display_a_map.cppUse dark colors for code blocks #include "SimpleLineSymbol.h" #include <QList> #include "ClassBreaksRenderer.h" #include "SimpleRenderer.h" #include "LabelDefinition.h" #include "TextSymbol.h" #include "ArcadeLabelExpression.h" #include "LabelDefinitionListModel.h" #include "PictureMarkerSymbol.h"
-
Create a helper method named
make
to define a label definition based on the trail name attribute (Label Definition() TRL
). Also define the label placement and symbol._NAME Display_a_map.cppUse dark colors for code blocks LabelDefinition* Display_a_map::makeLabelDefinition() { // Create a new text symbol. TextSymbol* labelTextSymbol = new TextSymbol(this); labelTextSymbol->setColor(QColor("white")); labelTextSymbol->setSize(12.0); labelTextSymbol->setHaloColor (QColor("black")); labelTextSymbol->setHaloWidth(2.0); labelTextSymbol->setFontFamily("Arial"); labelTextSymbol->setFontStyle(FontStyle::Italic); labelTextSymbol->setFontWeight(FontWeight::Normal); // Create a new Arcade label expression based on the field name: 'TRL_NAME'. ArcadeLabelExpression* labelExpression = new ArcadeLabelExpression("$feature.TRL_NAME", this); // Create and return the label definition. return new LabelDefinition(labelExpression, labelTextSymbol, this); }
-
Add a method named
add
. Define a variable to store a feature service URL accessing trailheads. Then use aTrailheads Layer() PictureMarkerSymbol
to draw trailhead hiker images, and use theLabelDefinition
created above to label each trailhead by its name.Display_a_map.cppUse dark colors for code blocks void Display_a_map::addTrailheadsLayer() { // Create a ServiceFeatureTable from the URL, create a FeatureLayer, and add that to the map's operational layers. QUrl trailheadsQUrl("https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0"); FeatureLayer* featureLayer = addFeatureLayer(trailheadsQUrl); // Create a new picture marker symbol that uses the trailhead image. QUrl trailheadImageQUrl("https://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png"); PictureMarkerSymbol* pictureMarkerSymbol = new PictureMarkerSymbol(trailheadImageQUrl, this); pictureMarkerSymbol->setHeight(18.0); pictureMarkerSymbol->setWidth(18.0); // Create a new simple renderer based on the picture marker symbol. SimpleRenderer* simpleRenderer = new SimpleRenderer(pictureMarkerSymbol, this); // Set the feature layer's renderer and enable labels. featureLayer->setRenderer(simpleRenderer); featureLayer->setLabelsEnabled(true); // Create the label definition. LabelDefinition* trailHeadsDefinition = makeLabelDefinition(); // Add the label definition to the layer's label definition collection. featureLayer->labelDefinitions()->append(trailHeadsDefinition); }
-
Update
setup
to call the newViewpoint() add
method.Trailheads Layer() Display_a_map.cppUse dark colors for code blocks void Display_a_map::setupViewpoint() { const Point center(-118.80543, 34.02700, SpatialReference::wgs84()); const Viewpoint viewpoint(center, 100000.0); m_mapView->setViewpointAsync(viewpoint); addOpenSpaceLayer(); addTrailsLayer(); addBikeOnlyTrailsLayer(); addNoBikeTrailsLayer(); addTrailheadsLayer();
-
Press Ctrl + R to run the app.
When the app opens, Trails feature layer is added to the map. The map draws a hiker icon for trails and displays the trail's name.
Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: