Learn how to apply renderers A renderer is a collection of rules and symbols used to display the data in a layer. Learn more and label definitions to a feature layer A feature layer (client-side) is a data layer that can access and display features from a feature service that has the same type of geometry and attribute fields. Learn more based on attribute values.

style a feature layer

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 A renderer is a collection of rules and symbols used to display the data in a layer. Learn more 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:

  1. You need an ArcGIS Location Platform or ArcGIS Online account.

  2. Your system meets the system requirements.

  3. The ArcGIS Maps SDK for Qt, version 300.0.0 or later is installed.

  4. The Qt 6.8.2 software development framework or later is installed.

Develop or Download

You have two options for completing this tutorial:

  1. Option 1: Develop the code or
  2. Option 2: Download the completed solution

Option 1: Develop the code

To start the tutorial, complete the Display a map tutorial. This creates a map to display the Santa Monica Mountains in California using the topographic basemap from the ArcGIS Basemap Styles service The ArcGIS Basemap Styles service, also referred to as the Basemap Styles service, is a location service that provides basemap styles and data for the world. It returns styles as Mapbox styles and web maps, and data as vector tiles and/or map tiles. It supports all of the styles in the ArcGIS Basemap style and Open Basemap style family. An ArcGIS Location Platform or ArcGIS Online account is required to use the service. Learn more .

Open a Qt Creator project

  1. Open the project you created by completing the Display a map tutorial.

  2. Continue with the following instructions to apply renderers and label definitions to a feature layer based on attribute values.

Add needed classes and declarations

  1. In the Projects window, open the Headers folder. Open the Display_a_map.h file.

  2. Add the LabelDefinition and FeatureLayer classes to the namespace.

    Display_a_map.h
    namespace Esri::ArcGISRuntime {
    class Map;
    class MapQuickView;
    class LabelDefinition;
    class FeatureLayer;
  3. Add the declarations for methods you will create.

    Display_a_map.h
    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();
  4. Save the file.

Create a function to add a feature layer

A feature layer can be added from a feature service A feature service is a data service that provides access to spatial and non-spatial data in feature layers, feature layer views, and tables. Learn more hosted in ArcGIS Online ArcGIS Online is a GIS mapping, analytics, data hosting, and content management software as a service (SaaS) product. It includes applications, tools, APIs, and location services for users and developers. It is subscription-based and requires an ArcGIS Online account. Learn more . Each feature layer contains features A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more with a single geometry A geometry is a geometric shape, such as a point, polyline, or polygon, that contains one or more coordinates and a spatial reference. Learn more type ( point A point is a type of geometry containing a single set of x,y coordinates and a spatial reference. Learn more , line A polyline is a type of geometry containing ordered point coordinates and a spatial reference. Learn more , or polygon A polygon is a type of geometry containing an array of rings and a spatial reference. Each ring contains an array of point coordinates, where the first and last point are the same. Learn more ), and a set of attributes Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more . 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 An operational layer is a layer used by a map or a scene to visualize geographic data. Operational layers are displayed on top of a basemap layer. Learn more . You will use this helper method throughout the tutorial as you add and symbolize various layers.

  1. In the project Headers folder of Qt Creator, double-click the Display_a_map.cpp file to open it. Add include statements to access the classes that will be used.

    Display_a_map.cpp
    #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 "FeatureLayer.h"
    #include "ServiceFeatureTable.h"
    #include "LayerListModel.h"
  2. Add a helper method named addFeatureLayer(const QUrl& url) that takes a feature service URL as an argument.

    Display_a_map.cpp
    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.

  1. Staying within the Display_a_map.cpp file, add include statements to access the classes that will be used.

    Display_a_map.cpp
    #include "FeatureLayer.h"
    #include "ServiceFeatureTable.h"
    #include "LayerListModel.h"
    #include "SymbolTypes.h"
    #include "UniqueValue.h"
    #include <QUrl>
    #include "SimpleFillSymbol.h"
    #include "UniqueValueRenderer.h"
  2. Add a new method named addOpenSpaceLayer().

    Display_a_map.cpp
    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);
    }
  3. Update setupViewpoint() method to call the newly added addOpenSpaceLayer() method.

    Display_a_map.cpp
    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();

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.

  1. Staying within the Display_a_map.cpp file, add include statements to access the classes that will be used.

    Display_a_map.cpp
    #include "SymbolTypes.h"
    #include "UniqueValue.h"
    #include <QUrl>
    #include "SimpleFillSymbol.h"
    #include "UniqueValueRenderer.h"
    #include "SimpleLineSymbol.h"
    #include <QList>
    #include "ClassBreaksRenderer.h"
  2. Add a global QUrl variable for the trails feature service.

    Display_a_map.cpp
    MapQuickView* Display_a_map::mapView() const
    {
    return m_mapView;
    }
    QUrl trailsQUrl("https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0");
  3. Add a new method named addTrailsLayer().

    Display_a_map.cpp
    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);
    }
  4. Again update the setupViewpoint() method to call the newly added addTrailsLayer() method.

    Display_a_map.cpp
    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();

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.

  1. Staying within the Display_a_map.cpp file, add the include statement to access the additional class that will be used.

    Display_a_map.cpp
    #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"
  2. Add a method named addBikeOnlyTrailsLayer() that contains a definition expression to filter for trails that permit bikes.

    Display_a_map.cpp
    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);
    }
  3. Add another method named addNoBikeTrailsLayer() with a definition expression to filter for trails that don’t allow bikes.

    Display_a_map.cpp
    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);
    }
  4. Again update the setupViewpoint() method to call the newly added addBikeOnlyTrailsLayer() and addNoBikeTrailsLayer() methods.

    Display_a_map.cpp
    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();

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.

  1. Staying within the Display_a_map.cpp file, add the include statement to access the additional classes that will be used.

    Display_a_map.cpp
    #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"
  2. Create a helper method named makeLabelDefinition() to define a label definition based on the trail name attribute (TRL_NAME). Also define the label placement and symbol.

    Display_a_map.cpp
    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);
    }
  3. Add another method named addTrailheadsLayer() that will define a variable to store a feature service URL accessing trailheads. Then use a PictureMarkerSymbol to draw trailhead hiker images, and use the LabelDefinition created above to label each trailhead by its name.

    Display_a_map.cpp
    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);
    }
  4. Finally, update the setupViewpoint() method once more to call the newly added addTrailheadsLayer() method.

    Display_a_map.cpp
    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();

Set developer credentials

For the final steps of this tutorial, click the tab below that corresponds to the authentication type (API key authentication or User authentication) that you chose when you completed the Display a map tutorial.

Be sure to also provide the same authentication (API key or user authentication Client ID/Redirect URL) that you used for the Display a map tutorial.

Set the API Key

  1. In the project Sources folder of Qt Creator, open the main.cpp file.

  2. Modify the code to set the accessToken using your API key access token (highlighted in yellow).

    main.cpp
    // The following methods grant an access token:
    // 1. User authentication: Grants a temporary access token associated with a user's ArcGIS account.
    // To generate a token, a user logs in to the app with an ArcGIS account that is part of an
    // organization in ArcGIS Online or ArcGIS Enterprise.
    // 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("");
    if (accessToken.isEmpty())
    {
    qWarning() << "Use of ArcGIS location services, such as the basemap styles service, requires" <<
    "you to authenticate with an ArcGIS account or set the API Key property.";
    }
    else
    {
    ArcGISRuntimeEnvironment::setApiKey(accessToken);
    }
  3. Save the main.cpp file.

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

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.

Alternatively, you can download the tutorial solution, as follows.

Option 2: Download the solution

  1. Click the Download solution link under Solution and unzip the file to a location on your machine.

  2. Open the .pro project file in Qt Creator.

Since the downloaded solution does not contain authentication credentials, you must set up authentication to create the developer credentials and add them to the project.

For the final steps of this tutorial, click the tab below that corresponds to the authentication type (API key authentication or User authentication) that you chose when you completed the Display a map tutorial.

Be sure to also provide the same authentication (API key or user authentication Client ID/Redirect URL) that you used for the Display a map tutorial.

Set developer credentials in the solution

Set the API Key

  1. In the project Sources folder of Qt Creator, open the main.cpp file.

  2. Modify the code to set the accessToken using your API key access token (highlighted in yellow).

    main.cpp
    // The following methods grant an access token:
    // 1. User authentication: Grants a temporary access token associated with a user's ArcGIS account.
    // To generate a token, a user logs in to the app with an ArcGIS account that is part of an
    // organization in ArcGIS Online or ArcGIS Enterprise.
    // 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("");
    if (accessToken.isEmpty())
    {
    qWarning() << "Use of ArcGIS location services, such as the basemap styles service, requires" <<
    "you to authenticate with an ArcGIS account or set the API Key property.";
    }
    else
    {
    ArcGISRuntimeEnvironment::setApiKey(accessToken);
    }
  3. Save main.cpp file.

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Run the solution

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: