QML building a legend

2724
2
Jump to solution
01-27-2016 06:35 PM
ISSRWEB
New Contributor II

Hi, I am creating an app with QT Creator and am wondering how i would go about creating a legend. I could not find a legend component.

I have tried creating a custom component (listview with a model), and i scan the layerItems and retrieve the image url.

However, the url i get (sample below) does not seem to be a http endpoint. it looks like it is going in to a custom image provider, however, i am unable to see the image in my listview.

qml: image://arcgisruntimeimageprovider/cdacd5e0-39ac-4167-9adb-29a6d7a3388f/legendItem

I was wondering if someone could point me in the general direction of creating a legend component.

I am fairly new to qml/qt so i apologize for any noob questions i may have.

Thanks

1 Solution

Accepted Solutions
LucasDanzinger
Esri Frequent Contributor

Hmm, the image provider image should work with the image. Maybe you can try the legend sample that the AppStudio team has created:

main.qml:

Map {
    id: map
    anchors.fill: parent
    extent: marylandExtent


    ArcGISTiledMapServiceLayer {
        url: "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"
    }


    ArcGISDynamicMapServiceLayer {
        id: dynamicService
        //url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/MapServer"
        //url: "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapSe..."
        //url: "https://gisapps.dnr.state.md.us/arcgis2/rest/services/AIMS/WaterAccess20140919/MapServer"
        url: "https://gisapps.dnr.state.md.us/arcgis2/rest/services/Environment/Natural_Filters/MapServer"
        onStatusChanged: {
            if( status === Enums.MapStatusReady){
                mylegendView.updateModel();
            }
        }
    }


    Envelope {
        id: marylandExtent
        xMax: -8519000
        yMax: 4814600
        xMin: -8501800
        yMin: 4821600
    }


    Rectangle {
        id: legendRectangle
        color: "lightgrey"
        radius: 5
        border.color: "black"
        opacity: 0.77
        width: parent.width * 0.3
        anchors {
            right: parent.right
            top: parent.top
            bottom: parent.bottom
            margins: 20 * scaleFactor
        }
    }


    LegendView {
        id: mylegendView
        map: map
        anchors.fill: legendRectangle
        anchors.margins: 10 * scaleFactor
    }
}









LegendView.qml

ListView {
    id: legendView


    property Map map


    model: legendModel


    spacing: 3
    clip: true
    
    section {
        property: "layerName"
        criteria: ViewSection.FullString
        delegate: legendSectionDelegate
        labelPositioning: ViewSection.InlineLabels
    }
    
    
    delegate: legendItemDelegate


    //--------------------------------------------------------------------------


    Component {
        id: legendSectionDelegate


        Item {
            width: parent.width
            height: textControl.height


            Text {
                id: textControl


                anchors.verticalCenter: parent.verticalCenter
                text: section
                width: parent.width
                font {
                    pointSize: 10
                    bold: true
                }
                color: "#4c4c4c"
                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
            }
        }
    }


    //--------------------------------------------------------------------------


    Component {
        id: legendItemDelegate


        Item {
            width: parent.width
            height: Math.max(legendImage.height, legendText.height)


            Image {
                id: legendImage
                anchors {
                    left: parent.left
                    leftMargin: 5
                    verticalCenter: parent.verticalCenter
                }


                source: image
                height: 30 * System.displayScaleFactor
                width: height
                fillMode: Image.PreserveAspectFit
            }


            Text {
                id: legendText


                anchors {
                    verticalCenter: parent.verticalCenter
                    left: legendImage.right
                    leftMargin: 4
                    right: parent.right
                }


                text: label
                color: "#4c4c4c"
                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
                font {
                    pointSize: 10
                }
            }
        }
    }


    //--------------------------------------------------------------------------


    ListModel {
        id: legendModel
    }


    function updateModel() {
        legendModel.clear();


        //console.log("Legend Layers", map.layerCount);


        for (var layerIndex = 0; layerIndex < map.layerCount; layerIndex++) {
            var layer = map.layerByIndex(layerIndex);
            if (!layer.visible) {
                continue;
            }


            switch (layer.type) {
            case Enums.LayerTypeArcGISTiledMapService :
                continue;


            default:
                break;
            }


            var legendInfos = layer.legend;


            //console.log("Legend Infos", legendInfos.length);


            for (var infoIndex = 0; infoIndex < legendInfos.length; infoIndex++) {
                var legendInfo = legendInfos[infoIndex];


                var legendItems = legendInfo.legendItems;
                //console.log("Legend Items", legendInfo.layerName, legendItems.length);


                for (var itemIndex = 0; itemIndex < legendItems.length; itemIndex++) {
                    var legendItem = legendItems[itemIndex];


                    legendModel.append(
                                {
                                    "layerName": legendInfo.layerName,
                                    "image": legendItem.image.toString(),
                                    "label": legendItem.label
                                });
                }
            }
        }
    }


    //--------------------------------------------------------------------------
}





























































View solution in original post

2 Replies
LucasDanzinger
Esri Frequent Contributor

Hmm, the image provider image should work with the image. Maybe you can try the legend sample that the AppStudio team has created:

main.qml:

Map {
    id: map
    anchors.fill: parent
    extent: marylandExtent


    ArcGISTiledMapServiceLayer {
        url: "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"
    }


    ArcGISDynamicMapServiceLayer {
        id: dynamicService
        //url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/MapServer"
        //url: "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapSe..."
        //url: "https://gisapps.dnr.state.md.us/arcgis2/rest/services/AIMS/WaterAccess20140919/MapServer"
        url: "https://gisapps.dnr.state.md.us/arcgis2/rest/services/Environment/Natural_Filters/MapServer"
        onStatusChanged: {
            if( status === Enums.MapStatusReady){
                mylegendView.updateModel();
            }
        }
    }


    Envelope {
        id: marylandExtent
        xMax: -8519000
        yMax: 4814600
        xMin: -8501800
        yMin: 4821600
    }


    Rectangle {
        id: legendRectangle
        color: "lightgrey"
        radius: 5
        border.color: "black"
        opacity: 0.77
        width: parent.width * 0.3
        anchors {
            right: parent.right
            top: parent.top
            bottom: parent.bottom
            margins: 20 * scaleFactor
        }
    }


    LegendView {
        id: mylegendView
        map: map
        anchors.fill: legendRectangle
        anchors.margins: 10 * scaleFactor
    }
}









LegendView.qml

ListView {
    id: legendView


    property Map map


    model: legendModel


    spacing: 3
    clip: true
    
    section {
        property: "layerName"
        criteria: ViewSection.FullString
        delegate: legendSectionDelegate
        labelPositioning: ViewSection.InlineLabels
    }
    
    
    delegate: legendItemDelegate


    //--------------------------------------------------------------------------


    Component {
        id: legendSectionDelegate


        Item {
            width: parent.width
            height: textControl.height


            Text {
                id: textControl


                anchors.verticalCenter: parent.verticalCenter
                text: section
                width: parent.width
                font {
                    pointSize: 10
                    bold: true
                }
                color: "#4c4c4c"
                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
            }
        }
    }


    //--------------------------------------------------------------------------


    Component {
        id: legendItemDelegate


        Item {
            width: parent.width
            height: Math.max(legendImage.height, legendText.height)


            Image {
                id: legendImage
                anchors {
                    left: parent.left
                    leftMargin: 5
                    verticalCenter: parent.verticalCenter
                }


                source: image
                height: 30 * System.displayScaleFactor
                width: height
                fillMode: Image.PreserveAspectFit
            }


            Text {
                id: legendText


                anchors {
                    verticalCenter: parent.verticalCenter
                    left: legendImage.right
                    leftMargin: 4
                    right: parent.right
                }


                text: label
                color: "#4c4c4c"
                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
                font {
                    pointSize: 10
                }
            }
        }
    }


    //--------------------------------------------------------------------------


    ListModel {
        id: legendModel
    }


    function updateModel() {
        legendModel.clear();


        //console.log("Legend Layers", map.layerCount);


        for (var layerIndex = 0; layerIndex < map.layerCount; layerIndex++) {
            var layer = map.layerByIndex(layerIndex);
            if (!layer.visible) {
                continue;
            }


            switch (layer.type) {
            case Enums.LayerTypeArcGISTiledMapService :
                continue;


            default:
                break;
            }


            var legendInfos = layer.legend;


            //console.log("Legend Infos", legendInfos.length);


            for (var infoIndex = 0; infoIndex < legendInfos.length; infoIndex++) {
                var legendInfo = legendInfos[infoIndex];


                var legendItems = legendInfo.legendItems;
                //console.log("Legend Items", legendInfo.layerName, legendItems.length);


                for (var itemIndex = 0; itemIndex < legendItems.length; itemIndex++) {
                    var legendItem = legendItems[itemIndex];


                    legendModel.append(
                                {
                                    "layerName": legendInfo.layerName,
                                    "image": legendItem.image.toString(),
                                    "label": legendItem.label
                                });
                }
            }
        }
    }


    //--------------------------------------------------------------------------
}





























































ISSRWEB
New Contributor II

Lucas, thanks for the answer....it was an issue on my end, I was binding it to the wrong listmodel.

After i fixed that issue, it worked fine.

However, thank you for the sample code, it was very helpful.

Thank You.

0 Kudos