qml maps show pointer image on each click - qt

I am having a code like this
Map {
id: map
anchors.fill: parent
plugin: Plugin {
name: "osm"
}
center: QtPositioning.coordinate(59.91, 10.75)
zoomLevel: 10
MapQuickItem {
id: transMarker
sourceItem: Image {
id: transImage
width: 50
height: 50
source: "trans.png"
}
}
MouseArea{
anchors.fill: parent
onClicked: {
var coord = map.toCoordinate(Qt.point(mouse.x,mouse.y));
transMarker.coordinate = coord;
console.log(coord.latitude, coord.longitude)
}
}
}
So on each click now the image moves from one coordinate to next coordinate, i would like to create a copy of the image in each place i click, How can i implement that?

You have to create a model(like ListModel) with a MapItemView that you use as a delegate to the MapQuickItem:
ListModel {
id: markermodel
dynamicRoles: true
}
Map {
id: map
anchors.fill: parent
plugin: Plugin {
name: "osm"
}
center: QtPositioning.coordinate(59.91, 10.75)
zoomLevel: 10
MapItemView{
model: markermodel
delegate: MapQuickItem {
coordinate: model.position
sourceItem: Image {
width: 50
height: 50
source: "trans.png"
}
}
}
MouseArea{
anchors.fill: parent
onClicked: {
var coord = map.toCoordinate(Qt.point(mouse.x,mouse.y));
markermodel.append({"position": coord})
}
}
}

Related

How to implement behavior animation on property changes QML

I am trying to change scale property when I click on image, but I would like for it to change slowly. For now I have it instantly when I click on the image (the image gets bigger).
Here are my images:
Here I clicked on the first image and it is slightly bigger than the rest.
Here is my code:
width: 1920
height: 1080
visible: true
title: qsTr("Hello World")
color:'black'
XmlListModel {
id: xmlModel
source: "movies.xml"
query: "/Movies/Movie"
XmlRole { name: "id"; query: "id/string()" }
XmlRole { name: "name"; query: "name/string()" }
XmlRole { name: "year"; query: "year/number()" }
XmlRole { name: "rating"; query: "rating/string()" }
XmlRole { name: "path"; query: "path/string()" }
}
ScrollView{
width:parent.width
height: 400
clip: true
ListView {
id:list
spacing:20
width: parent.width; height: parent.width*0.5
anchors.verticalCenter: parent.verticalCenter
model: xmlModel
clip:true
orientation: ListView.Horizontal
delegate:
Rectangle{ id: rect; width: 300;height: 300; color:'gray'
Image{
id:id
anchors.fill: parent
source:path
fillMode: Image.PreserveAspectFit
scale:focus?1.2:1
MouseArea{
id:area1
width:parent.width
height: parent.height
anchors.fill:parent
Behavior on scale {
PropertyAnimation{ duration: 4000 }
}
onClicked: {
id.scale=1.2
}
//hoverEnabled: true
/*onEntered: {
// hobbit.scale=1.2
id.focus=true
}
onExited: {
// hobbit.scale=1
id.focus=false
}*/
}
}
So, in my code I have Behavior on scale part, but nothing changes. I tried different options and nothing. Any advice? Help would be greatly appreciated.
Move the Behavior object outside the MouseArea object.
Image {
id: img
scale: focus ? 1.2 : 1
Behavior on scale {
PropertyAnimation{ duration: 4000 }
}
MouseArea {
onClicked: {
img.scale = 1.2
}
}
}

Prevent MouseArea from catching clicks within child rect

I have a fullscreen map, on which I added a mouse area:
Map {
id: map
anchors.fill: parent
plugin: osm
zoomLevel: 16
minimumZoomLevel: 13
maximumZoomLevel: 20
gesture.enabled: true
Rectangle {
id: infoPanel
// ...
Button {
// ...
}
}
MouseArea {
anchors.fill: parent
onPressed: {
infoPanel.visible = false
}
}
The infoPanel rect will ocasionally be made visible, overlaying the map with some information, and a button to trigger a certain action.
Now I have added the mouse area to the map in order to hide the info panel whenever the map is clicked, which works fine.
However, the info panel is also dismissed when the rectangle of the info panel itself is clicked.
How can I prevent the mouse area from the map to interfere with anything which is inside infoPanel?
you have to way:
you must set z value of info panel to map.z + 1 and define mouse area for info panel to capture mouse event. like below code
Map {
id: map
anchors.fill: parent
plugin: osm
zoomLevel: 16
minimumZoomLevel: 13
maximumZoomLevel: 20
gesture.enabled: true
Rectangle {
id: infoPanel
width: 100
height: 100
color: "red"
z: map.z + 1
MouseArea {
anchors.fill: parent
onClicked: {
print("info panel")
}
}
Button {
width: parent.width / 2
height: width
anchors.centerIn: parent
text: "button"
onClicked: {
print("button")
}
}
}
MouseArea {
anchors.fill: parent
onPressed: {
infoPanel.visible = false
print("map")
}
}
}
or just move your mouse area to up of info panel
Map {
id: map
anchors.fill: parent
plugin: osm
zoomLevel: 16
minimumZoomLevel: 13
maximumZoomLevel: 20
gesture.enabled: true
MouseArea {
anchors.fill: parent
onPressed: {
infoPanel.visible = false
print("map")
}
}
Rectangle {
id: infoPanel
width: 100
height: 100
color: "red"
MouseArea {
anchors.fill: parent
onClicked: {
print("info panel")
}
}
Button {
width: parent.width / 2
height: width
anchors.centerIn: parent
text: "button"
onClicked: {
print("button")
}
}
}
}

How to drag two components on map at a same time when they are placed on same coordinates on map in qml

I want to drag a two MapQuickItem which is declare inside the component and gets real time coordinates from map. MapQuickItem component is a rectangle having red and green colour. I want two drag both rectangle at same time when they are at same coordinates. How to drag both component at same time on map with same coordinates.
Map {
id: map
anchors.fill: parent
activeMapType: supportedMapTypes[1];
zoomLevel: 18
plugin: hereMaps
center: QtPositioning.coordinate(19.997454, 73.789803)
MapItemView {
id: markerItem
model: [
{ id: "marker1", color: "red" },
{ id: "marker2", color: "green" },
]
delegate: mapMarkerComponent
}
Component {
id : mapMarkerComponent
MapQuickItem {
id: mapMarker
coordinate: QtPositioning.coordinate(19.997454, 73.789803)
sourceItem: Rectangle {
id: handle
color: modelData.color
width: 40
height: 40
MouseArea {
drag.target: parent
anchors.fill: parent
}
onXChanged: {
mapMarker.x += x
}
onYChanged: {
mapMarker.y += y
}
}
}
}
}
Here the code that works for me, i.e. dragging marker2 implicitly drags marker1.
Map {
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(59.91, 10.75) // Oslo
zoomLevel: 14
MapQuickItem {
id: marker1
anchorPoint.x: 15
anchorPoint.y: 15
sourceItem: Rectangle {
id: rect1
width: 30
height: 30
radius: 15
color: "#8000FF00"
}
coordinate: QtPositioning.coordinate(marker2.coordinate.latitude + 0.005, marker2.coordinate.longitude)
}
MapQuickItem {
id: marker2
anchorPoint.x: 10
anchorPoint.y: 10
sourceItem: Rectangle {
id: rect2
width: 20
height: 20
radius: 10
color: "#800000FF"
MouseArea {
drag.target: parent
anchors.fill: parent
}
onXChanged: marker2.x += x;
onYChanged: marker2.y += y;
}
coordinate: QtPositioning.coordinate(59.91, 10.75)
}
}

How to get the list of QML Column Layout children?

I am working on some QML + c++ project and, I have a little problem with QML layouts:
I have two custom components :
First one: is a side-bar "SideTabBar.qml" (the purple rectangle in the image below).
Second one: is the element in the side-bar "SideBarElement.qml".
This image describes what I am talking about:
What I want is: highlight each side bar element on click.
To do so I am trying to iterate over the columnLayout children and lowlight them excepting the clicked one. But, I have not managed to make it works.
SideTabBar.qml:
Item {
id: sideTabBar
width: 70
height: parent.height
property string activeElement: ""
ColumnLayout{
id:sidebarLayout
anchors.fill: parent
spacing:2
SideBarElement{elementId:"a1";image:"../assets/product.svg"}
SideBarElement{elementId:"a2";image:"../assets/product.svg"}
Item {Layout.fillHeight: true}
}
}
SideBarElement.qml:
Item {
property alias image: sideBarElementicon.source
property string elementId: ""
id: sideBarElement
width:parent.width
Layout.preferredHeight: 70
Layout.alignment: Qt.AlignTop
Rectangle{
anchors.fill: parent
color:Qt.rgba(0,0,0,0)
}
Image {
id: sideBarElementicon
source: "genericIcon.png"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: 50
height: 50
}
MouseArea{
anchors.fill: parent
onClicked:{ sideTabBar.activeElement = elementId
// compiler does not even enter this loop.
// for(var child in Layout.children){
// console.log("this is a child")
// }
}
}
}
In this case it is better to work with a Repeater since it has an associated index and use a model to set the properties:
SideBarElement.qml
import QtQuick 2.0
Item {
property alias icon: sideBarElementicon.source
property bool highlight: false
width: parent.width
Rectangle{
anchors.fill: parent
color: highlight ? Qt.rgba(1,1,0,1) : Qt.rgba(0,0,0,0)
}
Image {
id: sideBarElementicon
source: "genericIcon.png"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: 50
height: 50
}
}
SideTabBar.qml
import QtQuick 2.0
import QtQuick.Layouts 1.11
Item {
id: sideTabBar
width: 70
height: parent.height
property int currentIndex: -1
ListModel{
id: elements
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
}
Rectangle{
anchors.fill: parent
color: "purple"
}
ColumnLayout{
id:sidebarLayout
anchors.fill: parent
spacing:2
Repeater{
model: elements
SideBarElement{
id: element
highlight: ix == currentIndex
icon: image
property int ix: index
Layout.preferredHeight: 70
Layout.alignment: Qt.AlignTop
MouseArea{
anchors.fill: parent
onClicked: currentIndex = ix
}
}
}
Item {Layout.fillHeight: true}
}
}

How to access the property of a GridView - or ListView - element

Here is the code, I create 4 buttons. When one is clicked I wanna that its color changes to red and the color of all the others change to black.
But looks like I could not access the color property.
Rectangle {
id: root
width: 200; height: 100
DelegateModel {
id: visualModel
model: ListModel {
ListElement { my_color: "red" }
ListElement { my_color: "black" }
ListElement { my_color: "black" }
ListElement { my_color: "black" }
}
groups: [
DelegateModelGroup { name: "selected" }
]
delegate: Rectangle {
id: item
height: 25
width: 200
color:my_color
MouseArea {
anchors.fill: parent
onClicked: {
console.log(visualModel.items.get(index).color)
for (var i = 0; i < root.count; i++){
if(index == i)
visualModel.items.get(i).color = "red";
else
visualModel.items.get(i).color = "black";
}
}
}
}
}
ListView {
anchors.fill: parent
model: visualModel
}
}
I advice you to use ExclusiveGroup from QML controls. Usually it is used for Action but it's possible to use it for any other Item. From the Qt docs:
It is possible to add support for ExclusiveGroup for an object or
control. It should have a checked property, and either a
checkedChanged, toggled(), or toggled(bool) signal.
So all we need is to add suitable property. Small example:
import QtQuick 2.5
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
Window {
width: 200
height: 400
ExclusiveGroup { id: exclusiveGroup }
ListView {
anchors.fill: parent
anchors.margins: 5
spacing: 2
model: 10
delegate: Rectangle {
id: myItem
property bool checked: false // <-- this is necessary
height: 30
width: parent.width
color: myItem.checked ? "lightblue" : "#DEDEDE"
border { width: 1; color: "#999" }
radius: 5
Text { text: "item" + (index + 1); anchors.centerIn: parent}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: myItem.checked = !myItem.checked;
}
Component.onCompleted: {
exclusiveGroup.bindCheckable(myItem);
}
}
}
}

Resources