Home > OS >  Qt Select At Most 1 Marker on Map
Qt Select At Most 1 Marker on Map

Time:12-23

In my code every marker that I clicked are selected(turn into green from red). I want just 1 can change. When I click another marker the marker I clicked before turns red again. Or When I click an empty area the marker I clicked before turns red again.

In qml my Item's code:

Component {
    id: hazardous_img

    MapQuickItem {
        id: hazardousitem
        anchorPoint.x: image.width/4
        anchorPoint.y: image.height
        coordinate: position
        property bool isClicked: false

        MouseArea {
            anchors.fill: parent
            onDoubleClicked: {
                mainwindow.hazardousIconClicked(mapview.toCoordinate(Qt.point(mouse.x,mouse.y)))
            }
            onClicked: {
                if (isClicked === false) {
                    image.source = "qrc:/grn-pushpin.png"
                    isClicked = true
                } else {
                    image.source = "qrc:/red-pushpin.png"
                    isClicked = false
                }
            }
        }
        sourceItem: Image {
            id: image
            source: "qrc:/red-pushpin.png"
        }
    }
}

CodePudding user response:

In QML this is usually done with using a ButtonGroup, but as you're not using AbstractButtons you need to write it yourself. Here is my solution for it.

I've used the ListModel to not only store the coordinates of each marker, but also a selected flag which is set to false by default. In the delegate I'm using the selected data role to show if a marker is selected or not.

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtLocation 5.15
import QtPositioning 5.15

ApplicationWindow {
    id: window
    width: 640
    height: 480
    visible: true
    title: qsTr("Map")

    ListModel { id: markerModel }

    Plugin {
        id: mapPlugin
        name: "osm"
    }

    Map {
        id: map
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(59.91, 10.75) // Oslo
        zoomLevel: 14

        MouseArea {
            anchors.fill: parent
            onDoubleClicked: {
                var coordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y))
                var jsonObject = JSON.parse(JSON.stringify(coordinate))
                jsonObject["selected"] = false
                markerModel.append(jsonObject)
            }

            onClicked: map.deselectAll()
        }

        MapItemView {
            model: markerModel
            delegate: markerDelegate
        }

        function deselectAll() {
            for (var i = 0; i < markerModel.count;   i)
                markerModel.setProperty(i, "selected", false)
        }

        Component {
            id: markerDelegate

            MapQuickItem {
                id: markerItem

                required property int index
                required property real latitude
                required property real longitude
                required property bool selected

                anchorPoint.x: waypointMarker.width / 2
                anchorPoint.y: waypointMarker.height / 2
                coordinate: QtPositioning.coordinate(latitude, longitude)

                sourceItem: Rectangle {
                    id: waypointMarker
                    width: 20
                    height: 20
                    radius: 20
                    border.width: 1
                    border.color: mouseArea.containsMouse ? "red" : "black"
                    color: markerItem.selected ? "red" : "gray"
                }

                MouseArea {
                    id: mouseArea
                    hoverEnabled: true
                    anchors.fill: parent
                    onClicked: {
                        map.deselectAll()
                        markerModel.setProperty(markerItem.index, "selected", true)
                    }
                }
            }
        }
    }
}

demo

CodePudding user response:

I came up with yet another solution without looping over all items in the model. It just stores the index of the selected marker in a dedicated property. This has the drawback that if the model order changes the index can become invalid, also potential multi selection is hard to handle, but on the other hand it is faster because it doesn't need to iterate over all items.

I experimented a lot with DelegateModel, it seems to be a perfect match if one could use it in combination with MapIteView, because of the groups and the attached properties like inGroupName. After that I've tried ItemSelectionModel, but it seems it is only intended to be used in combination with view, e.g. TreeView. I couldn't find out how to generate a QModelIndex in QML without a TreeView.

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtLocation 5.15
import QtPositioning 5.15

ApplicationWindow {
    id: root
    width: 640
    height: 480
    visible: true
    title: qsTr("Map")

    property int selectedMarker: -1

    Map {
        id: map
        anchors.fill: parent
        plugin: Plugin {
            id: mapPlugin
            name: "osm"
        }
        center: QtPositioning.coordinate(59.91, 10.75) // Oslo
        zoomLevel: 14

        MouseArea {
            anchors.fill: parent
            onDoubleClicked: {
                var coordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y))
                markerModel.append(JSON.parse(JSON.stringify(coordinate)))
            }

            onClicked: root.selectedMarker = -1
        }

        MapItemView {
            model: ListModel { id: markerModel }
            delegate: markerDelegate
        }

        Component {
            id: markerDelegate

            MapQuickItem {
                id: markerItem

                required property int index
                required property real latitude
                required property real longitude

                anchorPoint.x: waypointMarker.width / 2
                anchorPoint.y: waypointMarker.height / 2
                coordinate: QtPositioning.coordinate(latitude, longitude)

                sourceItem: Rectangle {
                    id: waypointMarker
                    width: 20
                    height: 20
                    radius: 20
                    border.width: 1
                    border.color: mouseArea.containsMouse ? "red" : "black"
                    color: markerItem.index === root.selectedMarker ? "red" : "gray"
                }

                MouseArea {
                    id: mouseArea
                    hoverEnabled: true
                    anchors.fill: parent
                    onClicked: root.selectedMarker = markerItem.index
                }
            }
        }
    }
}
  • Related