Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for Qt

Feature layer (dictionary renderer)

Sample Viewer View Sample on GitHub

Convert features into graphics to show them with mil2525d symbols.

Use case

A dictionary renderer uses a style file along with a rule engine to display advanced symbology. This is useful for displaying features using precise military symbology.

How to use the sample

Pan and zoom around the map. Observe the displayed military symbology on the map.

How it works

This sample loads a number of point, line, and polygon feature tables from a Runtime geodatabase. For each feature table, a FeatureLayer is created, and a DictionaryRenderer object is created and applied to the layer. Note that each layer needs its own renderer, though all renderers can share the DictionarySymbolStyle, in which case all layers will use the same symbology specification (MIL-STD-2525D in the case of this sample). Each layer is added to the map, and when all layers are loaded, the map's viewpoint is set to zoom to the full extent of all feature layers.

How it works

  1. Create a Geodatabase with a given path.
  2. Wait for geodatabase to completely load by connecting to the loadStatusChanged signal and checking the loadStatus.
  3. Cycle through each GeodatabaseFeatureTable from the geodatabase using Geodatabase.geodatabaseFeatureTables().
  4. Create a FeatureLayer from each table within the geodatabase.
  5. Wait for each layer to load by connecting to the layer's loadStatusChanged signal and checking the loadStatus.
  6. After the last layer has loaded, then create a new Envelope from a union of the extents of all layers.
    • Set the envelope to be the Viewpoint of the map view using MapView.setViewpoint(new Viewpoint(Envelope)).
  7. Add the feature layer to map using Map.operationalLayers.append(FeatureLayer).
  8. Create DictionaryRenderer and attach to the feature layer by setting FeatureLayer.renderer.

Relevant API

  • DictionaryRenderer
  • DictionarySymbolStyle
  • Geodatabase

Offline Data

Read more about how to set up the sample's offline data here.

Link Local Location
Mil2525d Stylx File <userhome>/ArcGIS/Runtime/Data/styles/arcade_style/mil2525d.stylx
Military Overlay geodatabase <userhome>/ArcGIS/Runtime/Data/geodatabase/militaryoverlay.geodatabase

Tags

DictionaryRenderer, DictionarySymbolStyle, military, symbol

Sample Code

import QtQuick 2.6
import QtQuick.Controls 2.2
import Esri.ArcGISRuntime 100.9
import Esri.ArcGISExtras 1.1

Rectangle {
    width: 800
    height: 600

    readonly property url dataPath: System.userHomePath + "/ArcGIS/Runtime/Data"

    // Create MapView that contains a Map with the Topographic Basemap
    MapView {
        id: mapView
        anchors {
            fill: parent
        }
        Map {
            id: map
            BasemapTopographic {}
        }
    }

    ProgressBar {
        id: progressBar_loading
        anchors {
            horizontalCenter: parent.horizontalCenter
            bottom: parent.bottom
            margins: 5
        }
        indeterminate: true
    }

    Geodatabase {
        property var gdbLayers: []

        id: geodatabase_militaryOverlay
        path: dataPath + "/geodatabase/militaryoverlay.geodatabase"

        onLoadStatusChanged: {
            if (Enums.LoadStatusLoaded === geodatabase_militaryOverlay.loadStatus) {
                const tables = geodatabase_militaryOverlay.geodatabaseFeatureTables;

                // Create a layer for each table
                for (let i = tables.length - 1; i >= 0; i--) {
                    //! [Apply Dictionary Renderer Feature Layer QML]
                    // Create a layer and set the feature table
                    const layer = ArcGISRuntimeEnvironment.createObject("FeatureLayer");
                    layer.featureTable = tables[i];

                    // Create a dictionary renderer and apply to the layer
                    const renderer = ArcGISRuntimeEnvironment.createObject("DictionaryRenderer",{
                                                                               dictionarySymbolStyle:
                                                                               //! [Create Dictionary Symbol Style QML]
                                                                               Factory.DictionarySymbolStyle.createFromFile(dataPath + "/styles/arcade_style/mil2525d.stylx")
                                                                               //! [Create Dictionary Symbol Style QML]
                                                                           });
                    layer.renderer = renderer;
                    //! [Apply Dictionary Renderer Feature Layer QML]

                    /**
                     * If the field names in your data don't match the contents of DictionarySymbolStyle::symbologyFieldNames(),
                     * you must set DictionaryRenderer::symbologyFieldOverrides to a map of key-value pairs like this:
                     * {
                     *   "dictionaryFieldName1": "myFieldName1",
                     *   "dictionaryFieldName2": "myFieldName2"
                     * }
                     * The following commented-out code demonstrates one way to do it, in a scenario where the dictionary
                     * expects the field name "identity" but the database table contains the field "affiliation" instead.
                     */
                    /**
                    let fieldOverrides = {
                        identity: "affiliation"
                    };
                    renderer.symbologyFieldOverrides = fieldOverrides;
                    */

                    gdbLayers.push(layer);

                    // Connect the layer's loadStatusChanged signal
                    layer.loadStatusChanged.connect(()=> {

                        // See if all the layers have loaded.
                        for (let j = 0; j < gdbLayers.length; j++) {
                            if (Enums.LoadStatusLoaded !== gdbLayers[j].loadStatus) {
                                return;
                            }
                        }

                        /**
                         * If we get here, all the layers loaded. Union the extents and set
                         * the viewpoint.
                         */
                        let bbox = gdbLayers[0].fullExtent;
                        for (let j = 1; j < gdbLayers.length; j++) {
                            bbox = GeometryEngine.unionOf(bbox, gdbLayers[j].fullExtent);
                        }
                        mapView.setViewpointGeometry(bbox);
                        progressBar_loading.visible = false;
                    });

                    // Add the layer to the map
                    map.operationalLayers.append(layer);
                }
            }
        }
    }
}