Customizing Vector Layers in a Qt Application: Colors, Line Styles, and Visibility

Vector layer symbology - Manya Technologies

When building a custom GIS application with QGIS API and Qt, one common requirement is to allow users to control how different layers (roads, rivers, boundaries, towns, etc.) are displayed on the map.

In this article, we’ll walk through how you can implement a GUI that enables users to:

  • Show or hide layers
  • Change colors for lines, polygons, and points
  • Switch line styles (solid, dashed, dotted, etc.)
  • Enable/disable fill colors for polygons

This flexibility ensures that your GIS tool is not only functional but also user-friendly for different visualization needs.


Example: Updating Layer Settings

Below is a simplified function that demonstrates how you can implement these controls using QGIS API + Qt Widgets.

We’ll rename our handler to LayerSettings::UpdateMapLayersSettings() for better readability.

void LayerSettings::UpdateMapLayersSettings()
{
    QgsVectorLayer *vectorLayer;
    QTableWidgetItem *tablewidgetitem;

    for (int row = 0; row < TOTAL_LAYERS_ROW; row++)
    {
        // Get vector layer for this row
        vectorLayer = mDisplayControlLayers.value(row);
        if (!vectorLayer || !vectorLayer->isValid())
            continue;

        // Check if layer visibility is toggled off
        tablewidgetitem = ui->tableWidgetMap->item(row, 0);
        if (tablewidgetitem->checkState() == Qt::Unchecked)
        {
            mLayerTreeView->setCurrentLayer(vectorLayer);
            mLayerTreeView->currentNode()->setItemVisibilityChecked(false);
            vectorLayer->setLabelsEnabled(false);
            continue;
        }

        // If visible → enable
        mLayerTreeView->setCurrentLayer(vectorLayer);
        mLayerTreeView->currentNode()->setItemVisibilityChecked(true);

        QColor strokeColor = Qt::black;
        QColor fillColor   = Qt::transparent;
        bool   fillEnabled = false;

        // --- Fetch fill option (from checkbox in UI)
        QWidget *tablewidget = ui->tableWidgetMap->cellWidget(row, 3);
        if (tablewidget != nullptr)
        {
            QCheckBox *chkbox = tablewidget->findChild<QCheckBox*>();
            fillEnabled = (chkbox && chkbox->isChecked());
        }

        // --- Fetch color (from tool button in UI)
        tablewidget = ui->tableWidgetMap->cellWidget(row, 4);
        if (tablewidget != nullptr)
        {
            QToolButton *toolButton = tablewidget->findChild<QToolButton*>();
            if (toolButton != nullptr)
            {
                QStringList colorList = toolButton->styleSheet().split(": ");
                if (colorList.size() > 1)
                {
                    QString colorString = colorList[1].trimmed();
                    colorString.remove(";");
                    fillColor.setNamedColor(colorString);
                    strokeColor = fillColor;
                }
            }
        }

        // --- Fetch line style (from combo box in UI)
        Qt::PenStyle lineStyle = Qt::SolidLine;
        tablewidget = ui->tableWidgetMap->cellWidget(row, 5);
        if (tablewidget != nullptr)
        {
            QComboBox *comboBox = tablewidget->findChild<QComboBox*>();
            if (comboBox != nullptr)
            {
                int index = comboBox->currentIndex();
                lineStyle = static_cast<Qt::PenStyle>((index + 1) % 6); 
            }
        }

        // --- Apply symbols based on geometry type ---
        if (vectorLayer->geometryType() == Qgis::GeometryType::Polygon)
        {
            auto *fillLayer = new QgsSimpleFillSymbolLayer(
                fillEnabled ? fillColor : Qt::transparent,
                strokeColor,
                lineStyle
            );
            auto *symbol = new QgsFillSymbol();
            symbol->changeSymbolLayer(0, std::move(fillLayer));
            vectorLayer->setRenderer(new QgsSingleSymbolRenderer(symbol));
        }
        else if (vectorLayer->geometryType() == Qgis::GeometryType::Line)
        {
            auto *lineLayer = new QgsSimpleLineSymbolLayer(strokeColor, 0.25, lineStyle);
            auto *symbol = new QgsLineSymbol();
            symbol->changeSymbolLayer(0, std::move(lineLayer));
            vectorLayer->setRenderer(new QgsSingleSymbolRenderer(symbol));
        }
        else if (vectorLayer->geometryType() == Qgis::GeometryType::Point)
        {
            auto *markerLayer = new QgsSimpleMarkerSymbolLayer();
            markerLayer->setColor(fillColor);
            auto *symbol = new QgsMarkerSymbol();
            symbol->changeSymbolLayer(0, std::move(markerLayer));
            vectorLayer->setRenderer(new QgsSingleSymbolRenderer(symbol));
        }
    }

    // Refresh map canvas after updates
    mMapCanvas->refresh();
}

How This Works

  1. Visibility Control – A QCheckBox in the table toggles the visibility of each layer.
  2. Color Picker – A QToolButton styled with background color lets the user choose stroke/fill colors.
  3. Line Style – A QComboBox provides style options like solid, dashed, dotted, etc.
  4. Geometry Handling – Depending on whether the layer is a polygon, line, or point, we apply the appropriate QGIS symbol renderer.
  5. Canvas Refresh – Finally, we refresh the map canvas so the user sees immediate changes.

Final Thoughts

By providing such customization options, your GIS application becomes far more interactive and user-centric. Whether you’re displaying roads, rivers, city points, or administrative boundaries, users can style them to suit their analysis needs.

If you’re interested in a full-fledged GIS solution, check out our flagship product PrithviGIS – a powerful QGIS-based platform for real-time geospatial visualization.

📩 For collaboration, demos, or project discussions, feel free to contact Manya Technologies.

Scroll to Top